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

C program calling malloc results in bus error?

提问人:tekkyprograms 提问时间:7/26/2023 最后编辑:Vlad from Moscowtekkyprograms 更新时间:7/26/2023 访问量:83

问:

我编写了这段代码来声明一个指针,然后为 int 类型动态分配 4 个字节的内存,然后在其中存储一些数据。 应指向保存 int 类型数据的地址。然后,程序应使用 .我还包含了从堆中释放已分配内存的函数。我不明白为什么我会收到总线错误。相同的代码已由对等节点执行,并且运行良好。我正在使用 Mac M2 并在 上运行代码。可能导致此错误的原因是什么?pp6dereferencing operatorfree()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 参数传递

评论


答:

4赞 Chris 7/26/2023 #1

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

就目前而言,您正在取消引用未初始化的指针,从而导致未定义的行为。如果成功,您还会发生(在本例中为短暂的)内存泄漏,因为以后无法释放此内存。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赞 Logan MacDougall 7/26/2023 #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赞 Vlad from Moscow 7/26/2023 #3

在 C 语言中,参数按值传递给函数。这意味着相对于您的程序,该函数处理 中声明的指针值的副本。foopmain

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

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

foo(p);

//...

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

正如你所看到的,它是在函数中声明的局部变量,它被更改了。原始指针保持不变。函数参数是函数的局部变量。ap

因此,当指针保持不变且未初始化时,例如取消引用指针p

*p = 6;

导致总线错误。

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

在 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;
}

注意两个方面。

第一种是将不带参数的函数声明为main

int main( void )

第二个是在 C 中(与 C++ 相反),您不需要转换从函数返回的指针。也就是说,你可以写malloc

*a = malloc(sizeof(int));

此外,在取消引用之前,您应该检查函数中更改的指针是否不是空指针。另一方面,可以为 null 指针调用该函数。pmainfree