十多年以前仔细研究过这个 char *s = "0123"。当时用的还是 VC6.
结果比较有意思(针对 VC6 ,之后的应该改进了)。
对于 Debug 版,“0123” 会被放到只读数据段里面(好像是叫.rdata). char* s 是个指向这个只读数据段中一小段数据的一个指针。任何对这个数据段的写操作都会引发段错误。
相应的这避免了两次调用相同的函数,结果不一致的问题。
比如下面的代码,假设可写,那么会有
test() {
char*s = "123";
printf("%s", s);
s[1] = 'a';
}
test();
test(); <--- 这里打印出来 1a3 ,和程序的语义不一致。
有意思的是上面的代码在 Release 版是没有出错的,打印出来两行 123 和 1a3 。
当时看了下的结果是,
对于 Debug 版,生成的 exe 有三个段,代码段(可执行),只读数据段(只读),普通数据段(可读可写)。
而对于 Release 版,连接器把所有三个段捏到一起去了,整个 exe 文件只有一个段,这个段可读可写可执行。
总之这个问题和系统的段页式内存管理,以及编译器连接器都有关系 |