据我所知,在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
有人可以帮我解释一下吗?
答案 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];
来启用它。