我正在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."); }
如评论所述,segfault发生在名为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()
.
这是一个错误或存在的问题,还是我做错了什么?
更多信息:我使用调试符号编译生锈,以便逐步查看HashMap代码以查找问题.看起来它甚至没有尝试执行new()函数,在调试代码时,HashMap::new()
在unwind.rs中直接进入调试器步骤直接执行此函数:
pub unsafe fn try(f: ||) -> ::core::result::Result<(), Box> { 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()) };
Segfault出现在cause.take()
函数中,我认为是因为my_ep.cause为null或无法访问.因此,某些东西会产生无效的异常,并且try
函数会阻塞它并给出段错误.这与从动态加载的库中调用HashMap代码有关,但我不知道它是如何相关的.
谢谢你的帮助.
编辑:我的平台是linux x64,我使用了git master从昨天(2014年10月28日)开始的新生锈.