【问题标题】:Why are constants stored in the text segment in a C memory map?为什么常量存储在 C 内存映射的文本段中?
【发布时间】:2012-10-11 04:48:46
【问题描述】:

您好,请考虑下面的代码 sn-ps 在 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

这里将全局变量从数据段移动到文本段。

为什么要从数据中移到文本段?

既然数据段是分为读区和读写区的,应该已经存放在读区的数据了吧?

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

【问题讨论】:

    标签: c linux memory memory-management


    【解决方案1】:

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

    $ 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 数字的总和?

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

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

    (“g”代表全局,“O”代表“对象”,而“F”代表函数。)

    【讨论】:

    • 有些常量甚至只存在于机器指令中。当您在 C 中编写 i = j+3; 时,3 常量很可能只存在于机器代码中(不在 .rodata 段中)。
    • @Zack 很好的解释。我完全同意你的观点。但是为什么在我的情况下,计数从数据段中减少并随着文本段增加?
    • @AbhishekSrinath 我不确定我是否理解您的问题。当global 是一个常规的全局变量时,自然是在.data 中。当您将其设为const 时,它已移至.rodatasize.rodata.text 合并为“文本”,因为两者都是只读的。这说明清楚了吗?
    【解决方案2】:

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

    如果它是一个静态变量,编译器可能会消除它,因为它未被使用,无论是否为常量。如果它是静态和常量,编译器可能会消除它,以便在它生成的代码中使用它的值。

    【讨论】:

      【解决方案3】:

      我要回到我之前的编辑。我相信,因为它永远不会改变它只是一个编译器优化,因为它们不能改变,所以根本不将常量存储在数据段中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-17
        • 2012-06-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-08
        • 1970-01-01
        相关资源
        最近更新 更多