为什么我用GCC做的最小编译exe是67KB?

我想创建一个非常小的编译exe,它是用C语言编写的.但我能设法得到的最小的是67KB.我正在使用MinGW.

我试过不使用任何头文件,这编译没有错误:

//no header
void main() {
 write(1, "Hello world!", 12);
}

如果我构建并运行它,GCC显示没有错误,但它也是67KB.

最佳答案 我只是在x86_64 Linux中试过这个,这可能与MinGW在这个级别上没什么不同,尽管你永远都不知道.

基本上,问题在于,即使没有任何内容从C库中提取,除非它被引用,CRT“startfiles”确实引用了一小部分内容,而这些内容又引用了其他一些内容,而“Hello world”最终会查找坏.这不是一个值得修复的问题,因为无论如何所有真正的程序都会引用这些核心功能.

启动文件的源代码是可用的,并且非常小,如果您选择,编译器允许您覆盖标准文件,因此优化它们并不是一件大事.它们是用汇编代码编写的,但您可以通过简单地删除行来删除大部分无关的垃圾.

但是,有一个黑客可以完全削减起始文件:

#include <unistd.h>

void _start (void) {
  write(1,"Hello world!", 12);
  _exit(0);
}

编译:gcc -nostartfiles t.c -s -static

哪个有效(偶然,见下文),并给我一个1792字节的文件大小.

为了比较,你的原始代码给出了738624个字节,使用相同的编译器,当我删除-static时,它会下降到4400个字节,但那就是作弊! (我的代码在没有-static的情况下实际上变大了,因为动态链接器元数据超过了write和_exit的代码).

偶然的一部分,是程序现在没有初始化堆栈指针.同样,对于所有其他全局状态,启动文件通常会处理.事实上,在x86_64 Linux上,这不是一个致命的问题(只是不要在生产中这样做,对吧?)但是,当我用-m32尝试它时,我在写入内部出现了分段错误.

可以通过为这些东西添加自己的初始化来解决这个问题,但是代码将不再是可移植的(它不是绝对可移植的).或者,直接调用write系统调用.

点赞