|
[PHP] 首先,来看如下一段程序
char* xyzstring = "hello,world!";
int main(void)
{
xyzstring[0] = 'a';
printf("%s\n",xyzstring);
return 0;
}
这段程序有问题吗?有,xyzstring的数据应该是静态数据,不能被修改。对,C语言的标准上也是这样说的。
果然是这样吗,我们做一个测试,使用四种编译器来看看实际运行的情况。
Codewarrior 8.0、Visual C++ 6.0、Borland C++ 5.6编译后运行都没有问题,都打出了"aello,world!",GCC 3.2编译后运行程序死掉。
为什么会出现这种情况,答案很简单,GCC将"hello,world!"放到了.text段中,而其它三种编译器则是将"hello,world!"到了.data段中。程序中,.text段是用来存放代码的,因此不能被修改,所以,当我们用xyzstring[0]来修改其中内容的时候,程序当然会当掉了。而.data段因为是数据段,是可以被修改的,因此程序不会当掉。
下面为了验证以上说法,我们使用GCC将源代码汇编成test.s
运行如下命令gcc -S test.c
.file "test.c"
.globl _xyzstring
.text
LC0:
.ascii "hello,world!\0"
.data
.align 4
_xyzstring:
.long LC0
.def ___main; .scl 2; .type 32; .endef
.text
LC1:
.ascii "%s\12\0"
.align 2
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
movl %eax, -4(%ebp)
movl -4(%ebp), %eax
call __alloca
call ___main
movl _xyzstring, %eax
movb $97, (%eax)
subl $8, %esp
pushl _xyzstring
pushl $LC1
call _printf
addl $16, %esp
movl $0, %eax
leave
ret
.def _printf; .scl 2; .type 32; .endef
以上是输出结果,我们看到test.s的头两行是
.globl _xyzstring
.text
说明_xyzstring是定义在了.text段中,现在,我们将其改称如下
.globl _xyzstring
.data
然后编译gcc -o test.exe test.s,接着执行test.exe,出现了什么,哈哈"aello,world!",执行没有问题了。
以上就是不同编译器对这种类型代码的解决方法,但是为了兼容,我们绝对不应该写出上面的代码
[/PHP]
http://blog.ifthen.net/archives/2003_10.html |
|