哪个部分将全局const变量存储在C ++可执行文件中?

时间:2017-03-04 06:18:00

标签: c++ c

据我所知,在C / C ++程序中,全局const变量将存储在可执行文件的.text(或.data - i'不确定)部分。但是当我试图验证时,我遇到了麻烦。

我有一个程序,它有一个像这样的全局const变量:

const unsigned char data[2030320] =
{
    0x00, 0x01, 0x00, 0x00, 0x00, 0x13, 0x01, 0x00, 0x00, 0x04, 0x00, 0x30, 0x42, 0x41, 0x53, 0x45,
    0xda, 0xec, 0xe7, 0xed, 0x00, 0x00, 0x01, 0x3c, 0x00, 0x00, 0x00, 0xc6, 0x47, 0x44, 0x45, 0x46,
    0x50, 0x4b, 0x6e, 0x76, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x4e, 0x47, 0x50, 0x4f, 0x53,
    0x64, 0x0a, 0x6e, 0x00, 0x00, 0x00, 0x02, 0x54, 0x00, 0x00, 0x0a, 0xdc, 0x47, 0x53, 0x55, 0x42,
    0x41, 0xfc, 0x50, 0x71, 0x00, 0x00, 0x0d, 0x30, 0x00, 0x00, 0x44, 0x16, 0x4c, 0x49, 0x4e, 0x4f,
    0x96, 0xa8, 0xc8, 0xcc, 0x00, 0x00, 0x51, 0x48, 0x00, 0x00, 0x00, 0x12, 0x4f, 0x53, 0x2f, 0x32,
    0x63, 0x8d, 0x51, 0xdd, 0x00, 0x00, 0x51, 0x5c, 0x00, 0x00, 0x00, 0x60, 0x63, 0x6d, 0x61, 0x70,
    0xc7, 0xfa, 0x84, 0xe4, 0x00, 0x00, 0x51, 0xbc, 0x00, 0x00, 0x8c, 0xf2, 0x67, 0x61, 0x73, 0x70,
    0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xde, 0xb0, 0x00, 0x00, 0x00, 0x08, 0x67, 0x6c, 0x79, 0x66,
    0x31, 0xb9, 0x1a, 0xce, 0x00, 0x00, 0xde, 0xb8, 0x00, 0x1b, 0x4e, 0x90, 0x68, 0x65, 0x61, 0x64,
    0xfe, 0x4d, 0xbc, 0xcd, 0x00, 0x1c, 0x2d, 0x48, 0x00, 0x00, 0x00, 0x36, 0x68, 0x68, 0x65, 0x61,
    0x07, 0x6b, 0x21, 0x2a, 0x00, 0x1c, 0x2d, 0x80, 0x00, 0x00, 0x00, 0x24, 0x68, 0x6d, 0x74, 0x78,
    0x04, 0x8c, 0x39, 0x67, 0x00, 0x1c, 0x2d, 0xa4, 0x00, 0x00, 0x7b, 0xf4, 0x6c, 0x6f, 0x63, 0x61,
    0x72, 0x06, 0x3f, 0xca, 0x00, 0x1c, 0xa9, 0x98, 0x00, 0x00, 0x7b, 0xf8, 0x6d, 0x61, 0x78, 0x70,
    0x21, 0x89, 0x01, 0x63, 0x00, 0x1d, 0x25, 0x90, 0x00, 0x00, 0x00, 0x20, 0x6e, 0x61, 0x6d, 0x65,
    0xc0, 0xe5, 0xda, 0x3d, 0x00, 0x1d, 0x25, 0xb0, 0x00, 0x00, 0x04, 0x3d, 0x70, 0x6f, 0x73, 0x74,
    0x0a, 0xfb, 0xdd, 0xeb, 0x00, 0x1d, 0x29, 0xf0, 0x00, 0x01, 0x54, 0xe2, 0x70, 0x72, 0x65, 0x70,
...
};

但是当使用dumpbin.exe(在Windows上)检查程序的文件.exe中的节的大小时。如果我删除变量,结果与结果相同,它总是如下

  4B1000 .data
    1000 .idata
    3000 .rdata
    2000 .reloc
    1000 .rsrc
    4000 .text
   10000 .textbss

有人可以帮我解释一下吗?

1 个答案:

答案 0 :(得分:1)

编译器很可能会优化掉变量,如果它可以证明它们从未被引用过。不幸的是,编译器一次只能看到一个转换单元(包含#include之后的源文件),所以禁止编译器优化未使用的全局变量。 Linker了解所有翻译单元,因此它可以(并将会)对未使用的全局变量进行优化。

使用MSVC编译代码(指定/O2):

const char a[1000000] = { 0 };

int main()
{
    return 0;
}

创建以下PE文件:

File Type: EXECUTABLE IMAGE

  Summary

        1000 .data
        1000 .gfids
        1000 .rdata
        1000 .reloc
        1000 .rsrc
        1000 .text

如果使用全局,则它将存储在PE文件的.rdata段中(请注意,如果全局为非常量,则会将.data段放在.rdata段中,因为const char a[1000000] = { 0 }; int main() { char c = a[1]; return 0; } 被读取-只要)。例如:

dumpbin

File Type: EXECUTABLE IMAGE Summary 1000 .data 1000 .gfids F5000 .rdata 1000 .reloc 1000 .rsrc 1000 .text 输出:

a

但是,在以下示例中,c仍然可以优化,因为/GS是未引用的局部变量。我发现在MSVC /LTCG编译器切换(其中指出整个程序优化和强制/LTCG会延迟代码生成直到链接阶段所以要执行的所有信息可以使用跨文件优化)实际上阻止了这种优化。

如果没有/GS/GS,则会按预期进行优化。添加/Gw会禁用全局数据优化,必须通过添加GMSMarker *myMarkerAutomaticSnippet = [[GMSMarker alloc] init]; marker.position = <Your cordinates>; marker.title = @“Title"; marker.snippet = @"Snippet"; marker.map = _mapView; [_mapView setSelectedMarker:marker]; 来启用它。