将库与C链接后的分段错误

将库与C链接后的分段错误,c,rust,static-linking,C,Rust,Static Linking,我试图静态链接到用Rust编写的库: #![crate_type = "staticlib"] #[no_mangle] pub extern "C" fn foo() { println!("bork!"); } 在C中使用以下代码: void foo(); int main() { foo(); return 0; } 使用rustc编译lib: rustc foo.rs 编译二进制文件并与库链接: gcc -g bar.c libfoo.a -ldl -lp

我试图静态链接到用Rust编写的库:

#![crate_type = "staticlib"]

#[no_mangle]
pub extern "C" fn foo() {
    println!("bork!");
}
在C中使用以下代码:

void foo();
int main()
{
    foo();
    return 0;
}
使用rustc编译lib:

rustc foo.rs
编译二进制文件并与库链接:

gcc -g bar.c libfoo.a -ldl -lpthread -lrt -lgcc_s -lpthread -lc -lm -o bar
在调试器内部运行:

(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.
rustc:

rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)

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

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

这是由标准库中的以下内容引起的:

/// 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);
    }
}
///print使用的标准输出!还有普林顿!宏
本地线程!{
静态本地存储:RefCell={
RefCell::新建(无)
}
}
// ...
pub fn_print(args:fmt::Arguments){
设结果=带有(| s|)的局部标准值{
如果s.借入\ U状态()==借入状态::未使用{
如果让一些(w)=s.借用{
返回w.write_fmt(args);
}
}
stdout().write_fmt(args)
});
如果让错误(e)=结果{
恐慌!(“打印到标准输出:{},e失败);
}
}
在这种情况下,
LOCAL\u STDOUT
中的
具有析构函数,因此当触碰线程局部变量时,可执行文件崩溃。我已经申请了,亚历克斯·克莱顿已经申请了


打印不需要初始化线程或任何东西;如果
LOCAL\u stdout
包含
None
(这是默认值),则可以回退到
stdout()
。只要传递
-pie
就足以说服可执行文件打印
bork而不是崩溃。

尝试关闭优化
rustc-g-C opt_level=0 foo.rs
gcc-O0-g bar.C libfoo.a-ldl-lpthread-lrt-lgcc_s-lpthread-lc-lm-o bar
会产生相同的结果
/// 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);
    }
}