0

As i understand, in C/C++ program, the global const variable will be stored in .text (or .data - i'm not sure) section of executable file. But when i try to verify that, i get trouble.

I have a program, it has a global const variable like that:

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,
...
};

But when a use the dumpbin.exe (on Windows) to check size of sections in file .exe of program. The result was same with result if i delete the variabe, it always as below

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

Could anyone help me to explain ??

TuanPM
  • 685
  • 8
  • 29

1 Answers1

1

Compiler will most likely optimize away variables if it can prove they are never referenced. Unfortunately, compiler can only see one translation unit (source file after #includes are... included) at a time so it's forbidden for a compiler to optimize out unused global variables. Linker has knowledge of all translation units so it can (and will) perform optimization on unused global variables.

Following code compiled using MSVC (/O2 specified):

const char a[1000000] = { 0 };

int main()
{
    return 0;
}

creates following PE file:

File Type: EXECUTABLE IMAGE

  Summary

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

If global is used then it will be stored in .rdata segment of PE file (note that if global is non-const it will be placed in .data segment as .rdata is read-only). For example:

const char a[1000000] = { 0 };

int main()
{
    char c = a[1];
    return 0;
}

And dumpbin output:

File Type: EXECUTABLE IMAGE

  Summary

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

However in the following example a could still be optimized out as c is unreferenced local variable. What I've found is that in MSVC /GS compiler switch (which states for Whole Program Optimization and forces /LTCG which delays code generation until link-stage so all information to perform cross-file optimizations are available) actually prevents this optimization.

Without /LTCG and /GS it is optimized out as expected. Adding /GS disables global data optimization and it has to be enabled by adding /Gw.

mpiatek
  • 1,313
  • 15
  • 16
  • You right. I have already confirmed. But it is just correct if the global variable is const. If i change data[] from const to non-const, it is always stored in .data even if unused . Could you help me to explain ? – TuanPM Mar 04 '17 at 11:06
  • consts can't go into `.data` because they are read-only - `.rdata` is for "read-only initialized data" as stated in PE specification. Your compiler might not optimize out unused non-const globals. For me (MSVC) unused non-const global doesn't make it into PE. – mpiatek Mar 04 '17 at 11:14
  • I am shocked to hear the compiler doesn't optimize away the array in the second example. – MikeMB Mar 04 '17 at 11:55
  • @MikeMB I appreciate sarcasm. Removed that unfortunate sentence – mpiatek Mar 04 '17 at 15:23
  • @mpiatek: No sarcasm at all. I really would have expected the compiler to optimize the global array away, even if you use it the way shown in your example, because that usage itself can be removed. – MikeMB Mar 04 '17 at 15:51
  • Btw.: I didn't downvote your answer – MikeMB Mar 04 '17 at 15:51
  • @MikeMB I rephrased whole answer. Added some details about MSVC not optimizing second example. Happy to learn something new today. – mpiatek Mar 04 '17 at 17:29