Sun的一个面试题(zz from newsmth)

来源:互联网 发布:现在淘宝开店怎么样 编辑:程序博客网 时间:2024/05/01 17:08

问题描述:

发信人: gpliu (云之飞扬), 信区: Programming
标  题: sun的一个面试题
发信站: 水木社区 (Tue May 31 17:26:03 2005), 站内


/* file1.c */
char buff[128];

/* file2.c */
extern char *buff;    /* Notice: extern char buff[] */

int main()
{
    *buff = 'a';
    return 0;
}

结果如下:
$ gcc file1.c -c
$ gcc file2.c -c
$ gcc file1.o file2.o -o ff
$ ./ff
Segmentation Fault

问,为何有这个结果?

我试了一下,在file2中换成extern char buff[]就可以,
但不知道为什么了..

解答:

发信人: adrift (随风飘荡), 信区: Programming
标  题: Re: sun的一个面试题
发信站: 水木社区 (Tue May 31 23:01:14 2005), 站内

不是这样。
要完全理解这个问题必须站在Compiler/Linker的角度来考虑。
以下用I386的指令集来说明

file1.c:
char buff[128];
大概被编译成下述指令(凭记忆,指令语法不见得正确)
public buff
buff db 128 dup(0)

file2.c:
extern char* buff;
*buff = 'a';
大概被编译成下述指令:
extrn buff:dword ; 指针
mov eax, buff; 直接寻址,取指针里面的地址
mov byte ptr[eax], 'a'

Link完成时假设file1.c/file1.obj中的buff被决定到地址0x20000000
于是上述指令实际是:
mov eax, [0x20000000] ; 执行时eax<=0x20000000地址处的dword值(0x00000000)
mov byte ptr[eax], 'a' ; Segment fault

运行期的错误就是这样产生的。

如果file2.c改成这样:
extern char buff[];
*buff = 'a'
则编译的指令大概如下:
extrn buff: byte ; 字符数组
mov buff, 'a' ; 直接寻址
Link完成后上述指令实际是
mov byte ptr[0x20000000], 'a'
这样就没有问题了

C/C++的好多令人疑惑的问题只要深入到二进制代码的层面就一目了然了
这个问题十年前就讨论过,现在想来还是很有意思的

启发:

在编译器的层面上char [] 与 char *的存储方式并不相

同.char []不分配符号的存储空间,而是用一个符量常量

来指明数组的首地址,而char *则为指针分配了存储空间

这种差异可能会造成一些隐藏的问题.

原创粉丝点击