【问题标题】:How to avoid C runtime (crt*.o) garbage如何避免 C 运行时 (crt*.o) 垃圾
【发布时间】:2026-01-26 07:55:02
【问题描述】:

我有两个 C 源文件

foo1.c:

#include <stdlib.h>
#include <stdio.h>

int main(void)
{
    puts("hello world");
    return 0;
}

foo2.c:

#include <stdlib.h>
#include <stdio.h>

void _start(void)
{
    puts("hello world");
    exit(0);
}

然后我在 i386 GNU/Linux 平台上编译它们:

$ #compile foo1
$ cc -o foo1 foo1.c
$ #compile foo2
$ cc -S foo2.c
$ as -o foo2.o foo2.s
$ ld -o foo2 -dynamic-linker /lib/i386-linux-gnu/ld-linux.so.2 -lc foo2.o
$ #notice that crt1.o and others are missing

从用户的角度来看,输出的可执行文件做同样的事情。

$ ./foo1
hello world
$ ./foo2
hello world

但它们是不同的:

$ wc -c foo1
5000
$ wc -c foo2
2208
$ objdump -d foo1 | wc -l
238
$ objdump -d foo2 | wc -l
35

即使我启用 gcc 的 -Os 选项来优化大小,

$ #compile foo1
$ gcc -o foo1 foo1.c -Os

它并没有小很多:

$ wc -c foo1
4908
$ objdump -d foo1 | wc -l
229

有什么方法可以让 GCC 优化 crt1.o 和我怀疑会导致这个臃肿文件大小的朋友的部分,而不使用非标准代码和奇怪的(在某些情况下可能有害)编译?我的 GCC 的版本字符串是“gcc (Debian 4.9.2-10) 4.9.2”。

【问题讨论】:

  • 您是否有想要减小文件大小的动机,或者这纯粹是出于好奇?
  • 看看here
  • @EugeneSh。 crt 中的符号已使用,但在我的示例案例中它们没有任何用处。
  • 如果他们没有做任何有用的事情 - 他们就不会被使用。
  • 如果无法通过链接器将其删除为未使用,则别无选择,只能使用不同的启动代码。

标签: c gcc crt


【解决方案1】:

使用 gcc/clang 你可以使用-nostartfiles,但是你使用的c 库可能依赖于它自己的_start() 实现来进行动态链接。由于您使用的是 Linux,因此我建议您使用 musl-libc 的静态构建。

或者,您可以只实现write()exit() 系统调用并将'\n' 添加到您的字符串中,通过使用_start() 而不是main() 完全避免使用c 库。如果您需要访问 argc、argv 和 envp,您将需要一些内联汇编来访问堆栈(Linux 将这些在堆栈上传递给所有 ELF 二进制文件,而不管架构如何)。

最近更新 更多