从dylib返回时macOS上的分段错误

时间:2018-02-20 08:09:00

标签: macos segmentation-fault rust

My Rust程序加载Rust写入的dylib以改善模块性。它在Linux上运行顺利,但在macOS上,第三次返回时会出现分段错误。

昨天问题更糟糕的是,在macOS上,第一次调用就是这样:

rustegram(4467,0x7fffad81d340) malloc: *** error for object 0x106817040: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6

在调试过程中,我发现问题在于使用对象作为函数调用参数。它们都是String,因此将它们转换为&str可以解决问题。

现在我需要传递复杂的值like serde_json::value::Valuetoml::Value

pub struct Plugin {
    name: String,
    config: TomlValue,
    plugins: Vec<Arc<Lib>>,
}

impl Plugin {
    pub fn run(&self, secret: String, body: JsonValue) -> Result<JsonValue, String> {
        if self.plugins.len() > 0 {
            // In a real program you want to cache the symbol and not do it every time if your
            // application is performance critical
            match unsafe { self.plugins[0].lib.get(b"init_bot\0") } {
                Ok(temp) => {
                    let f: Symbol<extern "C" fn(config: &TomlValue, secret: &str, body: &JsonValue) -> Result<JsonValue, String>> = temp;
                    //on mac it goes "segmentation fault" returning from the third call
                    println!("DEBUG: before");
                    let res = f(&self.config.clone(), &secret.clone(), &body.clone());
                    println!("DEBUG: after");
                    res
                },
                Err(e) => Err(format!("Error getting Symbol for {}: {}", self.name, e)),
            }
        }
        else {
            Err(format!("Lib {} not loaded", self.name))
        }
    }
}

在被调用的方法中,我已经进行了三次调试println!&#34; A&#34; &#34; B&#34;和&#34; C&#34;,每个操作前一个。输出是:

DEBUG: before
A
B
C
DEBUG: after
DEBUG: before
A
B
C
DEBUG: after
DEBUG: before
A
B
C
Segmentation fault: 11

有时候,它不是分段错误,而是提供非法指令:4&#34;。

有关完整代码,您可以查看my GitHub project

1 个答案:

答案 0 :(得分:0)

Matthieu M.指出,我没有正确解除引用。

在lib方面:

pub extern fn init_bot(ptr_config: *const TomlValue, secret: &str, ptr_body: *const JsonValue) -> Result<JsonValue, String>

在申请方面:

let f: Symbol<extern "C" fn(config: *const TomlValue, secret: &str, body: *const JsonValue) -> Result<JsonValue, String>> = temp;
f(Box::into_raw(Box::new(self.config.clone())), &secret, Box::into_raw(Box::new(body)))