Rust staticlib 与 C 链接后出现分段错误

kyk*_*cuk 5 c static-linking rust

我正在尝试静态链接到用 Rust 编写的库:

#![crate_type = "staticlib"]

#[no_mangle]
pub extern "C" fn foo() {
    println!("bork!");
}
Run Code Online (Sandbox Code Playgroud)

在 C 中使用以下代码:

void foo();
int main()
{
    foo();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用 rustc 编译 lib:

rustc foo.rs
Run Code Online (Sandbox Code Playgroud)

编译二进制文件并与库链接:

gcc -g bar.c libfoo.a -ldl -lpthread -lrt -lgcc_s -lpthread -lc -lm -o bar
Run Code Online (Sandbox Code Playgroud)

在调试器内运行:

(gdb) run
Starting program: /home/kykc/rusttest/bar 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff72117df in __cxa_thread_atexit_impl (func=<optimized out>, obj=<optimized out>, dso_symbol=0x0) at cxa_thread_atexit_impl.c:67
67  cxa_thread_atexit_impl.c: No such file or directory.
Run Code Online (Sandbox Code Playgroud)

海湾合作委员会:

gcc-4.8.real (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Run Code Online (Sandbox Code Playgroud)

生锈:

rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)
Run Code Online (Sandbox Code Playgroud)

它与 dylib 一起工作完全正常。我究竟做错了什么?

huo*_*uon 4

这里的问题是带有析构函数的线程局部变量只能在位置无关的可执行文件中使用(由于错误)。修复:将-pie标志传递给 gcc,或者等待一两天。

这是由标准库引起std::io::stdio::_printstd::io::stdio::LOCAL_STDOUT

/// Stdout used by print! and println! macros
thread_local! {
    static LOCAL_STDOUT: RefCell<Option<Box<Write + Send>>> = {
        RefCell::new(None)
    }
}

// ...

pub fn _print(args: fmt::Arguments) {
    let result = LOCAL_STDOUT.with(|s| {
        if s.borrow_state() == BorrowState::Unused {
            if let Some(w) = s.borrow_mut().as_mut() {
                return w.write_fmt(args);
            }
        }
        stdout().write_fmt(args)
    });
    if let Err(e) = result {
        panic!("failed printing to stdout: {}", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下, in具有析构函数,因此当触及线程局部变量时可执行文件会崩溃BoxLOCAL_STDOUT我已经提交了#24445,Alex Crichton 已经诊断并修复了根本原因

打印不需要初始化线程或任何东西;在包含的stdout()情况下有回退(这是默认的)。只需通过就足以说服可执行文件进行打印而不是崩溃。LOCAL_STDOUTNone-piebork!