我正在制作一个C++框架,该框架应该管理单独构建的自定义模块,这些模块在运行时作为共享库加载。这些模块必须使用自定义数据进行通信,因此我使用的是一个包含boost::每个模块可以用来设置和读取数据的任何值的无序映射。
该程序最近开始在对象的销毁顺序发生微小变化后,在关闭时出现segfault错误。经过一些跟踪,我想我发现了错误:尽管保存所有共享数据的unrdered_map由框架保留,但每个boost::any都包含(必须)由共享库中的代码创建的值,因为框架不知道每个键在编译过程中会包含什么值/类型。
如果在解除分配映射之前卸载所有共享库,boost::any在被销毁时会生成一个segfault,因为(我想)包含其值的指针已经从内存中卸载。如果我先删除映射,然后取消分配所有模块,则不会显示任何错误。因此,我假设,当创建并填充boost::任何值时,其内容都会以某种方式分配到与共享库相关的一些内存上,并且当共享库关闭时,试图删除boost::any会导致一切崩溃。
std::unordered_map<std::string, boost::any> shared_data;
std::vector<Module> dynamically_loaded_modules;
// RUNTIME DURING SOME MODULE EXECUTION
shared_data["SomeKey"] = my_unknown_typed_data;
// ON PROGRAM EXIT
dynamically_loaded_modules.clear(); // Calls dlclose()
shared_data.clear(); // This crashes
// ---------------
shared_data.clear();
dynamically_loaded_modules.clear(); // This does not crash
我的问题如下:
- 我对正在发生的事情的解释现实可行吗?我不太了解dlfcn.h是如何管理共享库的
- 先释放映射,然后再释放模块是否安全?或者我应该有一种方法让模块显式地删除每个提升:它们创建了什么?我需要那样做吗
您收到消息了吗;读取位置__vfptr"时发生访问冲突;?如果是这样的话,我认为以下陈述可以解释发生了什么以及为什么。假设map是在sharedlibrary.dll中创建的,然后在userclient.dll中的map中推送boost::any对象。任意对象存储的数据类型为int。然后一个新的模板类类型boost::any::holder<int>已创建。boost::any::holder<的地址;int>析构函数在userclient.dll的地址范围内。
好的,现在一切都清楚了,你卸载了userclient.dll,userlcient.dll的地址无效。最后,在sharedlirary.dll中销毁映射,boost::any::holder<int>应该调用对象的destrctutor,但boost::any::holder<int>析构函数对userlicnet.dll无效。dll已卸载。然后你会看到";读取位置__vfptr"时发生访问冲突;。