【问题标题】:Variable allocation in segments段中的变量分配
【发布时间】:2011-05-23 22:38:58
【问题描述】:

作为检查,我尝试了以下代码:

const int i = 100;
static int m = 90;
const int p = 40;
int x;

main()
{
    const int j = 40;
    static int k = 40;
    const int n;

    char *p = "Rama";
}

所以当我通过 gcc 编译器得到以下输出时,请告诉哪个变量去哪个段。我写的时候

size ./a.out

我明白了:

text   data   bss    dec   hex   filename
865    268     12   1145   479   ./a.out

【问题讨论】:

    标签: c gcc segments


    【解决方案1】:

    您可以使用nm。这是一个例子: test.c 包含您发布的示例:

    gcc -o test test.c
    nm -p -m test
    
    00001fb0 (__TEXT,__text) non-external (was a private external) dyld_stub_binding_helper
    00001fc4 (__TEXT,__text) non-external (was a private external) __dyld_func_lookup
    00002010 (__DATA,__data) non-external dyld__mach_header
    00002014 (__DATA,__data) non-external _m
    00002018 (__DATA,__data) non-external _k.1510
    0000200c (__DATA,__data) external _NXArgc
    00002008 (__DATA,__data) external _NXArgv
    00002000 (__DATA,__data) external ___progname
    00001000 (absolute) [referenced dynamically] external __mh_execute_header
    00002004 (__DATA,__data) external _environ
    00001ff0 (__TEXT,__literal4) external _i
    00001fd2 (__TEXT,__text) external _main
    00001ff4 (__TEXT,__literal4) external _p
    00002038 (__DATA,__common) external _x
    00001f70 (__TEXT,__text) external start
             (undefined [lazy bound]) external _exit (from libSystem)
    

    您可以使用here 描述的技术来控制变量转到哪个段。 (在 MS VC 中你可以使用#pragme data_seg("segname"))。

    【讨论】:

      【解决方案2】:

      变量和东西放在编译器想要放置的地方。您可以通过选项对编译器的行为方式进行一些选择。

      您可能想访问以下链接:

      http://en.wikipedia.org/wiki/A.out

      http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

      【讨论】:

      • 嘿,我访问了这些链接,但找不到任何适合我的东西。实际上我想知道哪个 var 去哪个段。十进制和十六进制是什么意思。感谢您的回复
      • 十六进制和十进制是测试和数据大小的总和。一个是十进制的,一个是十六进制的。 (1145)10 = (479)16
      【解决方案3】:

      通常,未初始​​化的数据会进入 BSS,而初始化的数据会进入 DATA(请参阅here)。

      但是 ISO C 并没有强制要求这种事情,这完全是一个实施问题。您问题中的dechex 分别是其他三个十进制和十六进制的总和:

      865 + 268 + 12 = 1145 = 0x479
      

      如果您真的想知道,可以使用各种工具,例如在编译时使用gcc -S 以获取汇编语言输出,或者使用nm 及其兄弟查看目标文件。

      【讨论】:

        【解决方案4】:

        我认为您对 staticconst 的含义感到困惑,这是可以理解的,因为您(和我!)通常在读过一次理论后就会忘记它们的含义。

        1) 首先,constconst 的意思是我们不会通过这个“引用”来改变变量的值。这对于函数参数非常有用,尤其是在使用指针时,这样您就不会编辑您不打算编辑的值。比如任意:

        void add(int* result, const int* a, const int* b)
        

        这个声明意味着如果我们不小心输入了a = result + b;,编译器应该抱怨并拒绝编译。在这种情况下,我们以这样一种方式命名变量,即使意外也不应该覆盖它们,但在更复杂的情况下,它可能会发生。

        然而,正如 pmg 所说,这并不意味着值不会改变;它只是意味着在谈论该地址/值的这个版本时,我们不会更改它。我的观点是,保护您不打算更改的参数很有用,以防您不小心尝试更改它们。如果您想要一个真正的固定值预处理器,通常会使用,例如#define TRUE 1.

        2) 现在static。静态的意思是“在这个编译单元之外不可见”。这就像,我强调,但不等同于类中私有的概念,但在这种情况下,我们谈论的是整个 C 文件。所以,如果我们在文件helloworld.c 中并且在顶部你写:

        static int x = 10;
        

        您不能在helloworld2.c 中使用该版本的x

        3) 虽然我们这样做了,但我们不妨换个词inlineinline 在我看来是一种更好的宏处理方式,它的意思是“编译器,你应该把它的结果代码放在你调用它的任何地方,而不是让我们花费一个函数调用”。无论如何,优化编译器可能会这样做,但这充当了尽可能内联的显式指令。

        总之,这些特性都是语言的控制部分,而不是变量在可执行文件的各个段中的位置。正如pmg 所说,编译器可以为所欲为。

        如果您想了解编译器做了什么,请使用gcc -S。这将为您提供来自gcc 的汇编语言输出,该输出将采用 AT&T 格式。尝试使用不同的 gcc -Ox 其中 x=0,1,2,3 标志来了解优化的工作原理。

        最后,值得注意的是a.out实际上只是一个名字;您的现代内核可能是在不支持a.out 二进制文件的情况下编译的。

        我认为这就是你真正想问的问题。

        【讨论】:

          猜你喜欢
          • 2017-09-02
          • 2019-08-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-11-28
          • 2018-12-18
          相关资源
          最近更新 更多