为什么ELF部分中的静态成员指针为零?

时间:2019-05-10 02:15:03

标签: c++ pointers static elf

编译以下代码,并检索 .ippalgo 部分,我注意到name字段为零,而其他字段按预期很好。

$ g++ a.cpp
$ objdump -s -j .ippalgo a.out

a.out:     file format elf64-x86-64

Contents of section .ippalgo:
 601040 00000000 00000000 02000000 01000000  ................
        ^^^^^^^^^^^^^^^^^
$ ./a.out
sizeof(char*): 8, sizeof(int): 4
name: 0x400648
name: abcdef

但是直接使用"abcdef"字符串更改 1。行之后,我似乎得到了正确的地址。

$ objdump -s -j .ippalgo a.out

a.out:     file format elf64-x86-64

Contents of section .ippalgo:
 601040 08064000 00000000 02000000 01000000  ..@.............
        ^^^^^^^^^^^^^^^^^
$ ./a.out
sizeof(char*): 8, sizeof(int): 4
name: 0x400608
name: abcdef

在任何一种情况下,main中的最后一个打印均带有正确的消息abcdef。我的问题是为什么我在第一种情况下得到零,如果有问题怎么解决?

#include <cstdio>

struct DataInfo {
    const char* name;
    int id;
    int type;
};

class Proxy {
public:
    const static char *name;
    const static int type;
    const static int id;
};

const char* Proxy::name = "abcdef";
const int   Proxy::id = 1;
const int   Proxy::type = 2;

__attribute__((used, section(".ippalgo")))
DataInfo ProxyInfo = {
    Proxy::name,  // 1. ok when set "abcdef" directly
    Proxy::type,
    Proxy::id
};

int main()
{
    printf("sizeof(char*): %lu, sizeof(int): %lu\n",
           sizeof(char*), sizeof(int));
    printf("name: %p\n", Proxy::name);
    printf("name: %s\n", ProxyInfo.name);
}

1 个答案:

答案 0 :(得分:3)

TL; DR Proxy::name不是const


静态数据的初始化分为两个阶段:常量(包括零初始化)和动态初始化。

在某些条件下,可以将两者合并,并且最终的初始化程序放置在二进制文件中,而不是在main()之前生成代码对其进行初始化。

您的编译器选择在一种情况下使用常量初始化,而在另一种情况下使用动态初始化。这是完全合法的,不需要编译器在二进制文件中的任何特定结构中放置常量。

在您的情况下,Proxy::name不是constProxy::id的事实Proxy::type可能会影响编译器的选择。它甚至不是一个编译时常量。也许编译器可以证明没有其他初始化代码可写入Proxy::name,但这是不平凡的,因为class Proxy具有外部链接。因此,即使持续传播和应用as-if规则在这里也无法使您失望。

constexpr在说服编译器使用常量初始化方面会更好。但是您至少需要将Proxy::name声明为const