段错误让人头疼

时间:2011-03-22 05:53:01

标签: c segmentation-fault

现在有以下代码有什么问题?

int main(){
union { 
        char arr[10];  
        int var;  
      } u;  
int *ptr_var= (int*) &(u.arr[1]);  
*ptr_var = 42; 
}

4 个答案:

答案 0 :(得分:4)

注意:已经给出了正确答案,这只是解释背景的另一种方式。

访问内存中的对象时,大多数计算机都要求对齐对象。这意味着必须将四字节(32位)对象放置在可被四个分割的地址上。这源于CPU使用数据总线与存储器连接的事实,在我们的示例中总线是32位。如果CPU支持未对齐的访问,则必须请求对内存的两次访问并将它们拼接在一起。相反,大多数架构认为这是非法操作。

在您的情况下,您从一个联合开始,该联合存储在一个偶数四字节的地址。然后你向前走一个字节并尝试在一个地址上访问一个int,该地址绝对不是该数量的偶数倍。

答案 1 :(得分:3)

你确定这是在给段错吗?标题是误导!!

旧架构上的AFAIK会导致总线错误。但正如this post所解释的那样,你最近没有看到公共汽车的错误。

这会导致总线错误,因为数组/ int联合确保字符数组arr也处于一个合理对齐的地址,该整数&arr[1]肯定不能正确对齐整数。然后,您尝试将sizeof(int)个字节存储到仅与单字节访问对齐的地址中。 Arghh !!!


答案 2 :(得分:1)

这里编译很简单。没有分段错误。编译器的输出究竟是什么?

在这里你可以看到:

#include <stdio.h>

int main()
{
    int *ptr_var;
    union
    { 
        char arr[10];  
        int var;  
    } u;  

    u.arr[0]='A';
    u.arr[9]='\0';
    ptr_var = (int*) &u.arr[1];

    *ptr_var = 0x2a;

    printf("%s\n", u.arr);
    printf("%d(d)=%x(x)\n",u.var, u.var);
}

答案是:

cpp/test/temp$ gcc union.c -o union
cpp/test/temp$ ./union 
A*
10817(d)=2a41(x)
cpp/test/temp$ gcc --version
gcc (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

这是移动位的好方法。也许你的段错误在程序的另一个区域。见这个测试:

*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);

ptr_var = (int*) &u.arr[1];
*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);

ptr_var = (int*) &u.arr[2];
*ptr_var = 0x10;
printf("%d(d)=%x(x)\n",u.var, u.var);

你得到:

16(d)=10(x)
4112(d)=1010(x)
1052688(d)=101010(x)

保重, BECO。

答案 3 :(得分:0)

这取决于架构。我猜这个标准可能会再次说这个行为是“未定义的”。在不同平台上运行时,我得到的结果不同:

1&GT; Linux on X86:运行正常没有问题 2 - ; sparc上的Solaris:“总线错误(核心转储)”。