为什么常量存储在C存储器映射中的文本段中?

时间:2012-10-20 23:00:18

标签: c linux memory memory-management

您好请考虑下面的代码片段在Linux机器(64位)上用gcc编译,并带有相应的内存映射

#include <stdio.h>

int global = 2;

int main(void)
{
    int local = 0;

    return 0;
}

text       data     bss     dec     hex filename

1092        500      16    1608     648 mem

这里因为有一个全局变量初始化为2。它已存储在数据段中 考虑将其设为const如下所示的情况

#include <stdio.h>

int const global = 2;

int main(void)
{
    int local = 0;

    return 0;
}

text       data     bss     dec     hex filename
1096        496      16    1608     648 mem

此处全局变量从数据段移动到文本段。

为什么它会从数据移到文本段?

由于数据段分为读取和读写区域,它应该存储在数据的读取区域中吗?

在代码中间初始化的未初始化的全局变量会发生什么?

3 个答案:

答案 0 :(得分:12)

在现代系统中,常量在为只读数据保留的目标文件的一部分中。该部分在默认模式下通过size命令与“text”(程序代码)部分混为一谈,但您可以使它为您提供更多详细信息:

$ size test.o  # compiled from the code in the question
   text    data     bss     dec     hex filename
     58       0       0      58      3a test.o

$ size -A test.o
test.o  :
section           size   addr
.text                6      0
.data                0      0
.bss                 0      0
.rodata              4      0
.comment            29      0
.note.GNU-stack      0      0
.eh_frame           48      0
Total               87

查看第一个命令生成的“文本”编号是第二个问题产生的.text.rodata.eh_frame数字的总和?

您可以使用.rodata命令判断常量是.text而不是objdump

$ objdump -t test.o | grep -w global
0000000000000000 g     O .rodata    0000000000000004 global

('g'代表全局,'O'代表'对象'而不是'F'代表函数。)

答案 1 :(得分:1)

文本段是只读的,因此通过将常量放在文本段中,编译器会确保它是真正的常量。它必须存储在某个地方,因为它被声明为可供其他目标文件访问,因此选择是数据和文本段。

如果它是静态变量,编译器可能能够消除它,因为它是未使用的,无论是否为常量。如果它是静态和常量的,编译器可能会将其消除,而不是在其生成的代码中使用它的值。

答案 2 :(得分:0)

我将回到之前的编辑。我相信,因为它永远不会改变它的简单编译器优化而根本不存储数据段中的常量,因为它们无法改变。