反汇编以下代码后:
#include <stdio.h>
static const char HELLO1[] = "Howdy";
int main(){
char hello2[6]="hello\0";
printf("%s",string);
}
我可以看到字符串 HELLO1 被声明为 .RODATA 段,这是可以理解的,因为常量变量被声明到此段中。
但是, hello2 也会声明为 .RODATA 段。但局部变量是否直接声明为堆栈?
你能解释一下为什么这个字符串被声明到这个片段吗?
答案 0 :(得分:3)
String literals存在于程序的生命周期
字符串文字有static storage duration,因此存在于内存中 为了节目的生命。
在程序开始时分配对象的存储空间 程序结束时取消分配。只有一个对象的实例 存在。在命名空间范围内声明的所有对象(包括全局 namespace)具有此存储持续时间,以及使用static声明的持续时间 或者是extern。
所以gcc
在static storage
二进制文件.RODATA
中实施ELF
进一步阐述......
char a[] = "Hello world A";
char* p = "Hello world P";
对于a
和p
,它们的字符串文字都有静态存储持续时间(这意味着它们都存储在.RODATA
中)与a
字符串不同literal被复制到此堆栈变量中,而p
只指向.RODATA
内存。这就是为什么你可以修改a
而不是p
注意:知道上面的参考文献来自c++
语法,但c
的原因是相同的
答案 1 :(得分:1)
C程序通常在内部使用memcpy和memset来在运行时构建堆栈的内容。虽然它依赖于平台,但像您这样的代码扩展到以下内容是很常见的:
#include <stdio.h>
static const char HELLO1[] = "Howdy";
int main(){
// hidden
static const char *__temporary_main_hello2 = "hello\0";
char hello2[6];
// hidden
memcpy(hello2, __temporary_main_hello2, sizeof(hello2));
printf("%s",string);
}
你现在可以看到为什么hello也在.rodata中。字符串的原始数据来自.rodata中的静态数据,但数组hello2的存储位于堆栈中。编译main时,编译器需要一种填充hello2的方法。如果平台有一种方便的方式来表示数据,那么它可能就是这样做的,但是使用优化良好的memcpy通常会更方便。