在 Rust 中调用使用 dlopen() 获得的函数指针时出现段错误

问题描述 投票:0回答:1

我目前正在使用 Rust 来使用

dlfcn.h
中定义的 POSIX 函数,目的是在单独的
.so
文件中调用函数。

该项目实际上包含 2 个板条箱:

  • 二进制文件加载共享对象并调用函数。
  • 动态库。

动态库有4行长,代码如下:

#[no_mangle]
pub extern "Rust" fn hello_world() -> String {
    String::from("Hello World !")
}

但是可执行二进制文件有点复杂,看起来像这样:

#![feature(str_from_raw_parts)]

fn open_dl(path: &str) -> Result<*mut libc::c_void, String> {
    let path = format!("{path}\0");

    let path: *const libc::c_char = unsafe { std::mem::transmute(path.as_ptr()) };
    let handle = unsafe { libc::dlopen(path, libc::RTLD_NOW) };

    if handle.is_null() {
        let dl_error: &str = unsafe {
            let ptr = libc::dlerror();
            let len = libc::strlen(ptr);
            std::str::from_raw_parts(std::mem::transmute(ptr), len)
        };

        return Err(String::from(dl_error));
    }
    Ok(handle)
}

fn get_symbol<T>(handle: *mut libc::c_void, symbol: &str) -> Result<&T, String> {
    let symbol_name = format!("{symbol}\0");
    let symbol = unsafe { libc::dlsym(handle, std::mem::transmute(symbol_name.as_ptr())) };

    if symbol.is_null() {
        let dl_error: &str = unsafe {
            let ptr = libc::dlerror();
            let len = libc::strlen(ptr);
            std::str::from_raw_parts(std::mem::transmute(ptr), len)
        };

        return Err(String::from(dl_error));
    }
    return unsafe { Ok(std::mem::transmute(symbol)) };
}

fn main() -> Result<(), String> {
    let handle = open_dl("./libfoo.so")?;

    // Tricky part, get the symbol with the correct signature and calling it
    let symbol: &fn() -> String = get_symbol(handle, "hello_world")?;
    let val = symbol(); // Blows up

    println!("{val}");

    Ok(())
}

我的问题是 get_symbol 似乎工作正常,获得的指针不为空,所以我希望调用它后面的函数不会导致任何问题,但是当我尝试这样做时,我得到了 SEGFAULT。你想知道为什么它会发生SEGFAULT吗?

rust segmentation-fault posix libc dynamic-library
1个回答
0
投票

get_symbol
的返回类型错误。

dlsym
返回
*mut c_void
(在函数指针的情况下)内部包含
Option<extern "C" fn(...)>

您必须将返回值直接转换为 Option,而不是引用。

请记住,在 Rust 中函数指针并不暗示指针语义,更不用说引用语义了。

© www.soinside.com 2019 - 2024. All rights reserved.