字符串常量引起的思考

记得以前看过一道这样的题目:

以下程序的执行结果是?

#include <stdio.h>                                                          

int main()
{
       char* p="Hello World"; 
       *(p+1)='a'; 
       printf("%sn",p);
       return 0; 
}

应该不难吧,不知道大家的答案是什么。

以下是我的一些解答:

对于指针p,他的大小是sizeof(p),一般为4,至于他指向的对象的大小是sizeof(char),那么在哪里存放字符串“Hello World”呢?

我们知道,程序编译时,编译器将代码翻译成汇编代码,然后汇编器将汇编代码翻译成机器代码(得到目标文件),最后链接器将目标文件链接成可执行文件。而目标文件和可执行文件的格式一般是类似的,由一个个section(段)组成,一般来说有代码段、数据段、bss段等,有些平台还会有.rodata段(只读数据段),用来放置只读变量(const变量)和字符串常量,这样不仅可以在语义上支持C++的const,而且操作系统还可以在加载的时候将.rodata映射为只读,这样对于这个段的修改会作为非法处理,保证了程序的安全。

(1)在Linux下可以用objdump查看目标文件或可执行文件中的内容:

objdump -x -s -d testchar

得到的结果如下:

字符串常量引起的思考

(左边是十六进制内容,右边是ASCII形式的内容)

可以看到字符串Hello World就在.rodata段中。

(2)接下来我们使用readelf来查看.rodata段的属性:

字符串常量引起的思考

得到:

字符串常量引起的思考

其中.rodata段的标志(Flg)为A(alloc),表示该段在进程中要分配空间,如果一个段可写的话,应该要有W(write)标志,如数据段(.data):

字符串常量引起的思考

也就是说,现在字符串“Hello World”在不可写的.rodata中,如果我们用指针直接修改的话,就会引发段错误。

所以程序的运行结果是:Segmentation fault应该说在Linux 下用gcc编译后,程序运行结果是:Segmentation fault

感谢@garbageMan的回复,确实,我说只是在gcc下的情况

@garbageMan:

很难说String literal 放在哪里

C语言并没有具体规定

放在哪里是编译器自己确定的

所以从一个编译结果推广到所有就是错误的



此外,C语言规定,修改String literal是一种UB

任何可能结果都有

不一定引发“段错误”

(3)数组中的情况

如果程序是这样呢:

#include <stdio.h>                                                          

int main()
{
     char p[]="Hello World";
     *(p+1)='a'; 
     printf("%sn",p);
     return 0; 
}

程序是可以正常运行的。

同样用objdump查看.rodata的内容:

字符串常量引起的思考

发现字符串已经不在.rodata中了。

对于数组,我们可以直接分配空间,像上面的数组p就可以直接在栈中分配空间来存放字符串“Hello World”,这样就可以修改字符串了。

以下内容我有点不肯定:

查看text段(代码段)中的内容,发现字符串在text段中。

字符串常量引起的思考

所以我的猜想是程序执行时,先将text段中的字符串复制到数组p在栈中的分配的内存里,这样就可以对字符串修改同时又不影响代码段中的内容(因为代码段一般是只读 的)不知我这个猜想对不对,希望各位解答一下……同时这个问题也感谢 @buzzerrookie的提醒。
原文链接: https://www.cnblogs.com/-Lei/archive/2013/01/12/2858027.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/75373

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月9日 下午4:59
下一篇 2023年2月9日 下午4:59

相关推荐