You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何我的Rust Hello-World可执行文件依赖libgcc_s?

问题

在Devuan Excalibur系统(类似无systemd的Debian Trixie,rustc版本1.84)中构建以下Rust程序:

fn main() {
    println!("Hello, world!\n");
}

使用cargo build --release编译后,执行ldd查看依赖得到:

$ ldd target/release/hello
    linux-vdso.so.1 (0x00007fff356f5000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f0b073c5000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0b071cf000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f0b0749c000)

而用GCC 14.2(gcc -O3)编译的C版Hello-World程序:

#include <stdio.h>
int main() {
    printf("Hello world\n");
    return 0;
}

其ldd结果无libgcc_s依赖:

$ ldd hello
    linux-vdso.so.1 (0x00007fff1d573000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8f1649f000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f8f166e5000)

请问Rust编译器在可执行文件中加入了什么内容导致该额外依赖,原因是什么?

解答

Rust程序依赖libgcc_s.so.1,核心原因是Rust的标准库或编译器生成的代码引入了GCC运行时支持逻辑,而这些逻辑在简单C程序中不会触发,具体细节如下:

  • 栈展开机制的默认启用:Rust默认用栈展开处理panic,这套逻辑依赖libgcc_s中的_Unwind_*系列函数(如_Unwind_RaiseException)。哪怕是看似简单的println!,其内部的错误处理路径也会包含栈展开相关代码。而GCC编译C程序时,默认不生成栈展开代码(除非用-fexceptions启用C++异常),简单printf调用不会触发这类依赖。
  • LLVM后端的代码生成选择:Rust基于LLVM编译,LLVM在生成某些代码时会选择调用libgcc_s的辅助函数,比如整数溢出检查、特殊浮点数运算处理等。而GCC编译简单C代码时,会直接生成对应机器码,无需依赖外部库实现这些逻辑。
  • 标准库的默认链接策略:Rust标准库默认会链接libgcc_s以支持跨平台的异常处理和通用运行时特性,哪怕程序没有显式用到这些功能。而GCC只有在代码用到需要libgcc_s的特性(如异常、特定数学函数)时才会链接它。

如果想消除该依赖,可以尝试两种方式:

  • 用-C panic=abort编译选项禁用栈展开,改用直接终止程序的panic处理:cargo build --release -C panic=abort
  • 通过-C link-args=-static-libgcc静态链接libgcc_s,避免动态依赖

内容的提问来源于Stack Exchange,提问作者einpoklum

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 17:10:08