我写了这段代码来声明一个指针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));
,则程序工作得非常好。为什么在前面的方法中使用它会导致总线错误?
3条答案
按热度按时间mgdq6dx11#
在函数
foo
中,参数a
是一个局部变量。您正在将malloc
的结果赋给它,但这对该函数调用之外的程序没有任何影响。就目前而言,您正在取消引用一个未初始化的指针,导致未定义的行为。如果
malloc
成功,您还会有一个(在本例中是短暂的)内存泄漏,因为您以后不能释放这个内存。要实现这一点,您需要传递一个指向该指针的指针。
字符串
您可能还希望养成检查
malloc
是否成功的习惯。chhqkbe12#
因为要更改指针的值,所以需要传递指针的地址。否则,您只需拥有地址的副本。
字符串
w8biq8rn3#
在C中,参数通过值传递给函数。这意味着相对于你的程序,函数
foo
处理的是在main
中声明的指针p
的值的副本。因此,函数内副本的任何更改都不会改变原始指针。
您可以按以下方式想象函数及其调用
字符串
正如您所看到的,在函数中声明的局部变量
a
被更改。原始指针p
保持不变。函数参数是函数的局部变量。因此,当指针
p
保持不变并且未被初始化时,则解引用指针,例如型
导致总线错误。
要在函数中更改对象(包括指针),需要通过引用传递它。
在C * 中,通过引用传递 * 意味着通过指向对象的指针间接传递对象。因此,取消引用传递的指针,您可以直接访问指针所指向的对象,并可以更改它。
所以你的程序应该看起来像下面这样
型
注意两个方面。
第一个是不带参数的函数
main
应声明为型
第二个是在C中(与C++相反),你不需要转换从函数
malloc
返回的指针。那就是你可以写型
此外,在
main
中解引用之前,还应该检查在函数中更改的指针p
是否不是空指针。另一方面,函数free
可以被调用用于空指针。