GCC编译生成的PE文件体积过大问题咨询(Windows 10环境)
Let’s break down exactly why you’re seeing this unexpected file size—this is a super common gotcha when learning about PE files on Windows, so you’re asking exactly the right questions!
The Big Culprit: Default Startup Code & Library Linking
When you run gcc file.c on Windows (assuming you’re using MinGW or a similar GCC port), GCC doesn’t just compile your tiny main function and call it a day. By default, it links in a bunch of C runtime (CRT) startup code that handles all the behind-the-scenes work your program needs to run properly:
- Initializing the C runtime environment (setting up the heap, stdio handles, etc.)
- Parsing command-line arguments to pass to
main - Calling your
mainfunction - Cleaning up resources after
mainexits - Handling exceptions and basic error reporting
These startup files (like crt0.o, crtbegin.o, crtend.o) aren’t tiny—they add tens of kilobytes on their own, even before considering your actual code. The optimization flags -O2, -Ofast, or -Os don’t affect this because they only optimize your user code, not the pre-linked startup code.
PE File Structure Overhead
Even if you stripped out all the startup code, PE files have inherent structural overhead that adds to the size:
- PE Headers & Section Tables: These metadata structures describe the file’s layout, entry point, imported libraries, etc.—they take up a few hundred bytes minimum.
- Section Alignment: Windows requires PE sections (like
.textfor code,.datafor variables) to be aligned to a minimum size (usually 4KB by default). So even if your actual code is only a few bytes, the.textsection will be padded to 4KB. Add in other mandatory sections like.rdata(read-only data) and.idata(import table for linked libraries), and you’re already looking at multiple 4KB chunks. - Import Table: Your default build links against libraries like
msvcrt.dll(the Microsoft C runtime) orlibgcc_s_dw2-1.dll(GCC’s support library). The import table needs to list all the functions your program uses from these libraries, which adds more bytes to the file.
Why Your Changes Didn’t Help
- Switching from
int main()toint main(void): This only changes how the compiler interprets the function signature, but it doesn’t affect the startup code that gets linked in. - Optimization flags: As mentioned, these optimize your code, but the bulk of the file size comes from the linked startup code and PE structure, not your 2-line
mainfunction.
How to Verify This
Try these commands to see what’s really going on:
- Compile without linking:
gcc -c file.c
The resultingfile.owill be tiny (probably less than 1KB)—this is just yourmainfunction, no extra stuff. - See the full linking process:
gcc -v file.c
Look for lines starting withcollect2—you’ll see all the startup files and libraries GCC is linking into your executable.
If You Want a Tiny PE File (For Learning)
If you want to create a minimal PE to explore the structure, you’ll need to bypass the default CRT linking:
- Use
-nostartfilesto skip the CRT startup code, then define your own entry point (usually_startinstead ofmain). You’ll have to handle PE initialization manually (like setting up the stack, callingExitProcess, etc.). - Add
-sto strip debug symbols and unnecessary metadata. - Avoid linking against external libraries if possible (call Windows API functions directly via syscalls or static linking).
Keep experimenting—this is a great way to deepen your understanding of how PE files work under the hood!
内容的提问来源于stack exchange,提问作者MrRobot

