为什么声明到 main 函数中的局部字符串是 Rodata 段内存的一部分?
Why local strings declared into the main function is part of Rodata segment memory?
反汇编后的代码如下:
#include <stdio.h>
static const char HELLO1[] = "Howdy";
int main(){
char hello2[6]="hello[=10=]";
printf("%s",string);
}
我可以看到字符串 HELLO1 被声明到 .RODATA 段中,这是可以理解的,因为常量变量被声明到该段中.
然而,hello2 也被声明到 .RODATA 段中。但是局部变量是直接声明到Stack对不对?
你能解释一下为什么这个字符串被声明到这个段中吗?
String literals 在程序的生命周期内存在
String literals have static storage duration, and thus exist in memory
for the life of the program.
The storage for the object is allocated when the program begins and
deallocated when the program ends. Only one instance of the object
exists. All objects declared at namespace scope (including global
namespace) have this storage duration, plus those declared with static
or extern.
所以gcc
在.RODATA
中实现static storage
在ELF
二进制
进一步阐述...
char a[] = "Hello world A";
char* p = "Hello world P";
对于a
和p
,它们的字符串文字具有静态存储持续时间(这意味着它们都存储在.RODATA
中),不同之处在于a
字符串文字被复制到这个堆栈变量中,而 p
只是指向 .RODATA
内存。这就是为什么您可以修改 a
但不能修改 p
注意:知道上面的引用来自 c++
语法,但 c
的原因是相同的
C 程序经常在内部使用 memcpy 和 memset 在运行时构建堆栈的内容。尽管它依赖于平台,但像您这样的代码通常会扩展为:
#include <stdio.h>
static const char HELLO1[] = "Howdy";
int main(){
// hidden
static const char *__temporary_main_hello2 = "hello[=10=]";
char hello2[6];
// hidden
memcpy(hello2, __temporary_main_hello2, sizeof(hello2));
printf("%s",string);
}
你现在可以明白为什么 hello 也在 .rodata 中了。字符串的原始数据来自 .rodata 中的静态,但数组 hello2 的存储在堆栈上。编译器需要一种在调用 main 时填充 hello2 的方法。如果平台有一种方便的方式来立即表示数据,则可以这样做,但通常为此使用优化良好的 memcpy 更方便。
反汇编后的代码如下:
#include <stdio.h>
static const char HELLO1[] = "Howdy";
int main(){
char hello2[6]="hello[=10=]";
printf("%s",string);
}
我可以看到字符串 HELLO1 被声明到 .RODATA 段中,这是可以理解的,因为常量变量被声明到该段中.
然而,hello2 也被声明到 .RODATA 段中。但是局部变量是直接声明到Stack对不对?
你能解释一下为什么这个字符串被声明到这个段中吗?
String literals 在程序的生命周期内存在
String literals have static storage duration, and thus exist in memory for the life of the program.
The storage for the object is allocated when the program begins and deallocated when the program ends. Only one instance of the object exists. All objects declared at namespace scope (including global namespace) have this storage duration, plus those declared with static or extern.
所以gcc
在.RODATA
中实现static storage
在ELF
二进制
进一步阐述...
char a[] = "Hello world A";
char* p = "Hello world P";
对于a
和p
,它们的字符串文字具有静态存储持续时间(这意味着它们都存储在.RODATA
中),不同之处在于a
字符串文字被复制到这个堆栈变量中,而 p
只是指向 .RODATA
内存。这就是为什么您可以修改 a
但不能修改 p
注意:知道上面的引用来自 c++
语法,但 c
的原因是相同的
C 程序经常在内部使用 memcpy 和 memset 在运行时构建堆栈的内容。尽管它依赖于平台,但像您这样的代码通常会扩展为:
#include <stdio.h>
static const char HELLO1[] = "Howdy";
int main(){
// hidden
static const char *__temporary_main_hello2 = "hello[=10=]";
char hello2[6];
// hidden
memcpy(hello2, __temporary_main_hello2, sizeof(hello2));
printf("%s",string);
}
你现在可以明白为什么 hello 也在 .rodata 中了。字符串的原始数据来自 .rodata 中的静态,但数组 hello2 的存储在堆栈上。编译器需要一种在调用 main 时填充 hello2 的方法。如果平台有一种方便的方式来立即表示数据,则可以这样做,但通常为此使用优化良好的 memcpy 更方便。