为什么Rust的可执行文件通常比C 的要大?

编程语言 2026-07-12

我编译了这个Rust文件 simple_rust.rs

#![no_std]

pub fn add(a: i32, b: i32) -> i32 {
    a + b
}

使用 rustc simple_rust.rs -C opt-level="z" --crate-type lib,rustc版本1.94.0,得到文件 libsimple_rust.rlib

我随后编译了这个C 文件 simple_c.c

int add(int a, int b) {
    return  a+b;
}

使用 gcc -c simple_c.c,gcc版本15.01,得到文件 simple_c.o

我注意到 libsimple_rust.rlib 的大小是5248字节,simple_c.o 的大小是1288字节(两者均在Ubuntu Linux下编译)。因此Rust二进制文件的大小大约是C 二进制文件的4 倍。

请注意,这个问题 的答案主要与Rust标准库默认被静态链接到Rust二进制文件中有关,与C 编译器+ 链接器处理库的方式不同。不过据我所知,上述示例中并没有链接任何库。尽管如此,我在这里看到的资料是,Rust的 *.rlib文件不仅包含目标代码,还包含LLVM位码、元数据和符号表。

因此我猜这些附加内容在二进制文件体积偏大方面起了主要作用,但也许我还漏掉了什么。

解决方案

在以上所有评论的帮助下,我找到了自己的答案。

简短的回答是:Rust二进制文件其实并不比C 二进制文件大。

(至少在一般情况下并非如此,在我修订后的示例中,Rust二进制实际上更小。)

长回答如下:在我使用 arobjdump 工具仔细查看Rust *.rlib 二进制后,发现其中包含一个元数据文件(*.rmeta)和一个对象文件(*.o)。令人惊讶的是,那个对象文件并不包含任何代码,因此add函数似乎被编译进了元数据文件。事实上,Rust的元数据文件可以包含所谓的MIR代码,见 此处

我随后把这个文件

#![no_std]

pub fn fibonacci(n: u32) -> u64 {
    match n {
        0 => 0,
        1 => 1,
        _ => fibonacci(n - 1) + fibonacci(n - 2),
    }
}

作为输入交给rustc,在 *.rlib 文件中找到了一个大小为1184字节的对象文件,其中实际包含了我的函数代码的文本段。

最后为了对比,我还编译了这个C 文件:

unsigned long long fibonacci(unsigned int n) {
    if (n == 0)
        return 0;
    if (n == 1)
        return 1;
    return fibonacci(n - 1) + fibonacci(n - 2);
}

得到的对象文件大小为1480字节。此外,仅查看两个对象文件的文本段,我发现从Rust源代码生成的机器代码比C 编译器生成的少12字节。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章