我正在用 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。