Rust:从动态加载库执行特定代码行时出现段错误

2023-12-23

我正在用 Rust 编写一个简单的基于插件的系统,以获得使用该语言的一些技能和经验。我的系统动态加载库并在运行时执行它们以初始化每个插件。从动态加载的库执行代码时,我遇到了一个有趣的段错误问题。

这是加载和运行插件初始化函数的代码:(这部分工作正常)

pub fn register_plugins<'rp>(&'rp mut self)
{
    let p1 = match DynamicLibrary::open(Some("librust_plugin_1.so")) {
            Ok(lib) => lib,
            Err(error) => fail!("Could not load the library: {}", error)
    };
    let s1: extern "Rust" fn(&PluginSystem) = unsafe {
        match p1.symbol("init") {
            Err(error) => fail!("Could not load function init: {}", error),
            Ok(init) => mem::transmute::<*mut u8, _>(init)
        }
    };
    s1(&self.ps);
}

这是插件库中的 init 函数:

#[no_mangle]
pub fn init(ps:&mut PluginSystem)
{
    ps.register_plugin("ps1"); //<-- Segfault is in this method
    ps.add_new_hook_with_closure("onLoad", "ps1", "display greeting.", 10, test1);
    println!("Initialized plugin.");
}

正如评论所述,段错误发生在名为 ps 的 PluginSystem 结构体的 register_plugin 函数内。该结构是从调用方法(在第一个代码块中)借用的。

这是PluginSystem中的register_plugin函数:

pub fn register_plugin(&mut self, plugin_name: &'s str)
{
    if ! self.plugins.contains_key(&plugin_name) {
        let hm = HashMap::new(); //<-- Segfault Here
        self.plugins.insert(plugin_name, hm);
    };
}

执行时出现段错误HashMap::new()在此代码块中;

我尝试以不同的方式实现此功能,如下所示:

pub fn register_plugin(&mut self, plugin_name: &'s str)
{
    match self.plugins.entry(plugin_name) {
                Vacant(entry) => {
                        entry.set(HashMap::new()); //<-- Segfault Here
                    }
                Occupied(mut entry) => {  }
            }
}

但我遇到了完全相同的问题。

如果我跳过 register_plugin 函数,并运行动态加载库中的其他代码,则它可以正常工作。事实上,唯一出现此段错误的代码是HashMap::new().

这是一个错误还是现有问题,或者我做错了什么?

更多信息: 我使用调试符号编译 Rust,以便单步执行 HashMap 代码来查找问题。看起来它甚至没有尝试执行 new() 函数,在调试代码时,在单步执行时HashMap::new()调试器直接进入 unwind.rs 中的该函数:

pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box<Any + Send>> {
    let closure: Closure = mem::transmute(f);
    let ep = rust_try(try_fn, closure.code as *mut c_void,
                  closure.env as *mut c_void);
    return if ep.is_null() {
        Ok(())
    } else {
        let my_ep = ep as *mut Exception; //<-- Steps into this line
        rtdebug!("caught {}", (*my_ep).uwe.exception_class);
        let cause = (*my_ep).cause.take(); //<-- Segfaults Here
        uw::_Unwind_DeleteException(ep);
        Err(cause.unwrap())
    };

段错误发生在cause.take()函数,我认为这是因为 my_ep.cause 为空或无法访问。所以有些东西正在生成一个无效的异常,并且try函数被阻塞并给出段错误。这与从动态加载库调用HashMap代码有关,但我不知道它是如何关联的。

谢谢你的帮助。

编辑: 我的平台是 linux x64,截至昨天(2014 年 10 月 28 日),我使用的是 git master 最新构建的 Rust。


我在 GitHub 上提出了一个关于此问题的问题 (here https://github.com/rust-lang/rust/issues/18521),用一个最小的测试用例,几个小时内就解决了。

基本上,这是因为 rustc 默认在构建可执行文件时静态链接 libstd,并在构建库时动态链接。 所以 main 使用静态 libstd,而在运行时加载 plugin.so 时,插件使用动态 libstd。之后就会发生奇怪的内存问题。

通过添加修复-C prefer-dynamicrustc 作为主要可执行文件。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rust:从动态加载库执行特定代码行时出现段错误 的相关文章

随机推荐