C 程序调用 malloc 导致总线错误?

问题描述 投票:0回答:3

我编写了这段代码来声明一个指针

p
,然后为int类型动态分配4个字节的内存,然后在其中存储一些数据。
p
应指向保存 int 类型数据
6
的地址。然后程序应该使用
dereferencing operator
打印出指针变量中的数据。我还包含了
free()
函数来从堆中释放分配的内存。我不明白为什么我收到总线错误。相同的代码已由同行执行,并且运行得非常好。我正在使用 Mac M2 并在
vscode
上运行代码。什么可能导致此错误?

#include <stdio.h>
#include <stdlib.h>

void foo(int *a){
    a = (int*)malloc(sizeof(int));
}

int main(){
    int *p;
    foo(p);
    *p = 6;
    printf("%d",*p);
    free(p);
    return(0);
}

这是错误消息:

zsh: bus error

请注意,如果我要删除

foo()
函数并用
p = (int*)malloc(sizeof(int));
替换调用行,那么程序就可以正常工作。为什么在之前的方法中使用它会导致总线错误?

c malloc parameter-passing pass-by-reference pass-by-value
3个回答
3
投票

在你的函数

foo
中,参数
a
是一个局部变量。您将
malloc
的结果分配给它,但这对此函数调用之外的程序没有影响。

就目前而言,您正在取消引用未初始化的指针,从而导致未定义的行为。如果

malloc
成功,您还会遇到(在本例中是短暂的)内存泄漏,因为您以后无法释放该内存。

要完成此操作,您需要将指针传递给指针。

void foo(int **a) {
    *a = malloc(sizeof(int));
}

int main(void) {
    int *p;
    foo(&p);
    *p = 6;
    printf("%d", *p);
    free(p);

    return 0;
}

您可能还想养成检查

malloc
是否成功的习惯。


2
投票

因为要改变指针的值,所以需要传递指针的地址。否则,您只需拥有地址副本即可。

#include <stdio.h>
#include <stdlib.h>

void foo(int **a){
    *a = malloc(sizeof(int));
}

int main(){
    int *p;
    foo(&p);
    *p = 6;
    printf("%d",*p); // 6
    free(p);
    return(0);
}

0
投票

在 C 中,参数按值传递给函数。这意味着相对于您的程序,函数

foo
处理在
p
中声明的指针
main
的值的副本。

因此,函数内副本的任何更改都会使原始指针保持不变。

您可以按以下方式想象该函数及其调用

foo(p);`

//...

void foo( /*int *a */.){
    int *a = p;
    a = (int*)malloc(sizeof(int));
}

如您所见,它是在更改的函数内声明的局部变量

a
。原始指针
p
保持不变。函数参数是函数的局部变量。

要更改函数内的对象(包括指针),您需要通过引用传递它。

在 C 中,通过引用传递意味着通过指向对象的指针间接传递对象。因此,取消引用传递的指针,您可以直接访问指针指向的对象并可以更改它。

所以你的程序应该如下所示

#include <stdio.h>
#include <stdlib.h>

void foo( int **a )
{
    *a = malloc(sizeof(int));
}

int main( void )
{
    int *p;

    foo( &p );

    if ( p != NULL )
    { 
        *p = 6;
        printf( "%d\n", *p );
    }

    free(p);

    return 0;
}

注意两个方面。

第一个是不带参数的函数maon,应声明为

int main( void )

第二个是在 C 中你不需要转换从函数 malloc 返回的指针。那就是你可以写

*a = malloc(sizeof(int));

并且您还应该在

p
中取消引用之前检查函数内更改的指针
main
是否不是空指针。

© www.soinside.com 2019 - 2024. All rights reserved.