为什么声明为main函数的局部字符串是Rodata段内存的一部分?

时间:2016-10-02 18:45:53

标签: c memory assembly reverse

反汇编以下代码后:

#include <stdio.h>

static const char HELLO1[] = "Howdy";

int main(){
char hello2[6]="hello\0";
printf("%s",string);
}

我可以看到字符串 HELLO1 被声明为 .RODATA 段,这是可以理解的,因为常量变量被声明到此段中。

但是, hello2 也会声明为 .RODATA 段。但局部变量是否直接声明为堆栈

你能解释一下为什么这个字符串被声明到这个片段吗?

2 个答案:

答案 0 :(得分:3)

String literals存在于程序的生命周期

  

字符串文字有static storage duration,因此存在于内存中   为了节目的生命。

Static storage duration

  

在程序开始时分配对象的存储空间   程序结束时取消分配。只有一个对象的实例   存在。在命名空间范围内声明的所有对象(包括全局   namespace)具有此存储持续时间,以及使用static声明的持续时间   或者是extern。

所以gccstatic storage二进制文件.RODATA中实施ELF

进一步阐述......

char a[] = "Hello world A";
char* p  = "Hello world P";

对于ap,它们的字符串文字都有静态存储持续时间(这意味着它们都存储在.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通常会更方便。