为本地静态const变量生成的符号?

时间:2018-09-12 19:16:59

标签: c++ linker

我在共享库中使用了RapidJSON,从某个时候开始定义这样的方法:

    template<unsigned parseFlags, typename SEncoding, typename TEncoding, typename InputStream, typename OutputStream>
    RAPIDJSON_FORCEINLINE void ParseStringToStream(InputStream& is, OutputStream& os) {
//!@cond RAPIDJSON_HIDDEN_FROM_DOXYGEN
#define Z16 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
        static const char escape[256] = {
            Z16, Z16, 0, 0,'\"', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'/',
            Z16, Z16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,'\\', 0, 0, 0,
            0, 0,'\b', 0, 0, 0,'\f', 0, 0, 0, 0, 0, 0, 0,'\n', 0,
            0, 0,'\r', 0,'\t', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            Z16, Z16, Z16, Z16, Z16, Z16, Z16, Z16
        };
#undef Z16
//!@endcond

我不明白的是为什么这会导致重定位:

readelf的输出:

823: 0000000000051b00   256 OBJECT  UNIQUE DEFAULT   14 _ZZN9rapidjson13GenericReaderINS_4UTF8IcEES2_NS_12CrtAllocatorEE19ParseStringToStreamILj0ES2_S2_9PhpStreamNS4_11StackStreamIcEEEEvRT2_RT3_E6escape

如果变量不是外部变量,为什么将符号与STB_GNU_UNIQUE绑定?不仅仅是指令指针的静态偏移就足以获取此数据?

1 个答案:

答案 0 :(得分:1)

函数似乎已被内联,因为已显式请求内联,但是在编译器内联指令时,它决定仅发出e:\Work\Dev\StackOverflow\q052302083>test.exe Enter n (invalid, to exit): 6 Results for 6 (with a step of: 2): 6 4 2 4 6 Enter n (invalid, to exit): 7 Results for 7 (with a step of: 2): 7 5 3 1 3 5 7 Enter n (invalid, to exit): 8 Results for 8 (with a step of: 2): 8 6 4 2 4 6 8 Enter n (invalid, to exit): 9 Results for 9 (with a step of: 2): 9 7 5 3 1 3 5 7 9 Enter n (invalid, to exit): 3 Results for 3 (with a step of: 2): 3 1 3 Enter n (invalid, to exit): 2 Results for 2 (with a step of: 2): 2 Enter n (invalid, to exit): 1 Results for 1 (with a step of: 2): 1 Enter n (invalid, to exit): q 数组的一个副本,链接器将合并该数组的一个副本跨翻译单元,因此整个程序中只有一个副本,因此编译器需要发出一个符号,以便该函数的每个内联副本都可以找到escape

(注意:从技术上讲,标准要求在带有外部链接的内联函数的主体中声明的escape局部变量具有唯一的地址。但是,我查看了源代码,看来{{ 1}}未被使用,因此这个唯一的地址是不可观察的;编译器可以选择将该数组的内容内联到每个转换单元中,但是,每个转换单元浪费了256个字节。)