C 32位和64位之间的行为差异
以下代码段在64位Ubuntu 14.04上执行,而在32位Ubuntu 14.04中出现seg错误。gcc版本在4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04)中相同C 32位和64位之间的行为差异,c,C,以下代码段在64位Ubuntu 14.04上执行,而在32位Ubuntu 14.04中出现seg错误。gcc版本在4.8.4(Ubuntu 4.8.4-2ubuntu1~14.04)中相同 #包括 主要() { int*a; int*b; *a=40; b=a; printf(“%x………%p………..%d\n”、*a、a、*a); } 在32位系统上,如果两个操作中的任何一个都完成,则相同的操作也会起作用- 注释掉b=a 添加a=malloc(sizeof(int))之前*a=40 有人能解
#包括
主要()
{
int*a;
int*b;
*a=40;
b=a;
printf(“%x………%p………..%d\n”、*a、a、*a);
}
在32位系统上,如果两个操作中的任何一个都完成,则相同的操作也会起作用-
a=malloc(sizeof(int))代码>之前*a=40李>
有人能解释一下这一观察结果吗?这不是32位与64位的问题,而是使用不指向有效内存地址的指针的问题。在代码段中,您声明了指针*a
和*b
,但实际上没有将它们指向任何位置,从而导致未定义的行为
使用指针时,总是立即分配足够的内存,或将它们指向现有的相应变量
例如,所有后续语句都是有效的:
int *a = NULL;
int *b = malloc(sizeof(int));
int c = 42;
int *d = &c;
通过不初始化它们,它们将指向任意位置<代码>*a=40
可能是“偶然”为您工作的,因为它可能指向您当时可以访问的内存空间。但是,在一般情况下,此代码段应该在任一操作系统中产生一个分段错误
如果您不打算将指针指向一个有效的内存地址,请考虑将其初始化为<代码> null ,以避免出现悬空指针。您永远不应该取消引用
NULL
指针,但在尝试这样做之前,您可以始终检查指针是否为NULL
。例如:
int *a = NULL;
if ( a != NULL ) {
*a = 42;
}
int *b = a;
if ( b != NULL ) {
printf("%d\n", *b);
}
此代码段不会打印任何内容,因为*a
和*b
都将为NULL
,但您的代码不会产生分段错误
值得一提的是,我在Debian 64位系统上也遇到了一个分段错误
[编辑以集成@AnT、@tuple\u cat和@Weather Vane的反馈]原始代码具有未定义的行为。您没有为
a
分配有效的内存地址,因此它有一个随机地址。取消对它的引用,将40次写入分配给随机内存,以便任何事情都可以发生。malloc
修复了错误,但是如果您不调用free(a)
,那么您就有了一个内存地址。将a
分配给b
不会更改任何此行为。打开编译器警告:警告C4700:未初始化的局部变量“a”已使用如果不添加2,则这是未定义的行为,因为您正试图写入未分配的内存。1不会更改任何内容,因为您没有在任何地方使用b
。int*a*a=40不管你使用什么编译器或操作系统,@Saurabh如果你在过马路前不看两边,有时你会被车撞到,有时你不会。解决方法不是试图找出你什么时候可以不朝两边看就过马路,而是每次都朝两边看。我不明白这与动态记忆有什么特别的关系。你可以只做intc;int*a=&c
从而获得有效的a
和*a
。这里不需要涉及动态内存。“指针”的概念与动态内存没有任何联系。而且,malloc
返回void*
。就是这样。@AnT感谢您的反馈,我集成了它以使答案更通用:当使用指针时,它们应该指向有效的地方。@tuple_cat感谢您指出这条线索,我不知道这是不必要的。:)您能否添加一个解释,说明何时使用指针总是将其初始化为NULL
?取消引用NULL
指针将不起作用。但是+1。
int *a = NULL;
if ( a != NULL ) {
*a = 42;
}
int *b = a;
if ( b != NULL ) {
printf("%d\n", *b);
}