当动态库中的指针仍被其他库使用时,如何删除该指针




目前,我正在测试一些动态库,并且在数据管理/删除方面遇到了一些问题。。。如何"通知"指针无效?

我需要的是:线程安全从其库中删除数据并使DataContainers Ptr无效的方法或线程安全的解决方法。

我尝试过的:

使用共享/弱指针=任何人都可以删除它(库被卸载,但指针仍然存在于另一个库中,并在那里删除它,但不知道如何删除。(

可能的解决方案:
-保留一个DataContainer列表,并在库卸载时手动将其设置为nullptr
-不要使用Ptr,使用"索引到矢量位置",并在每次需要数据时查找

简单示例:

class Data
{
public:
Data(std::string Str) : SomeStr(Str) {}
std::string SomeStr;
};
struct DataContainer
{
Data* m_Data = nullptr;
};
int main()
{
// This vector is static inside a Dynamic Library so we need to use UniquePtr,
// to be sure it gets deleted inside its Library when unloaded
// if we could use SharedPtr/WeakPtr it would be too easy... but it could get deleted by anyone
// Protected by Mutex
std::vector<std::unique_ptr<Data>> DataHolder;
DataHolder.push_back(std::make_unique<Data>("Example Str"));
// this could maybe inside another Dynamic Library
DataContainer Container;
Container.m_Data = (*DataHolder.begin()).get();
// As example instead of using a Dynamic Library that would get unloaded here
DataHolder.clear();
// Cannot use m_Data here, it got deleted by the DataHolder but Container don't know that
std::cout << "Str: " << Container.m_Data->SomeStr << std::endl;
return 0;
}

shared_ptr/weak_ptr就是您所需要的。保持所有权的模块对对象具有shared_ptrs,但它只允许其他模块获得weak_ptrs。其他模块(不应该拥有所有权(每次需要数据时都必须临时从weak_ptr中取出shared_ptr,并且在访问数据后必须立即销毁每个shared_ptr。

如果你不持有这个不变量,你需要在像onPointerInvalidated这样的模块之间进行一些外部同步,但这是一个更糟糕的设计。

至于线程安全,如果你保留shared_ptr,没有人可以破坏对象(除非有人做了像delete shared_ptr_.get()这样的恶意行为(。这意味着使用者和所有者之间有一个契约:使用者在短时间内锁定shared_ptr(从而延迟销毁(如果有的话((,而删除对象的所有者不担心任何悬空指针。

我同意,我认为共享/弱指针应该起作用。这就是我实现它的方式:

class Data
{
public:
Data(std::string Str) : SomeStr(Str) {}
std::string SomeStr;
};
struct DataHolder {
std::vector<std::shared_ptr<Data>> data;
std::weak_ptr<Data> get_data(size_t idx) {
return std::weak_ptr<Data>(data[idx]);
}
};
struct DataContainer
{
std::weak_ptr<Data> m_Data;
};
int main()
{
// This vector is static inside a Dynamic Library so we need to use UniquePtr,
// to be sure it gets deleted inside its Library when unloaded
// if we could use SharedPtr/WeakPtr it would be too easy... but it could get deleted by anyone
// Protected by Mutex
DataHolder theDataHolder;
theDataHolder.data.push_back(std::make_shared<Data>("Example Str"));

DataContainer Container;
Container.m_Data = theDataHolder.get_data(0);
// container is passed to a method inside the shared lib
auto t = shared_lib_entry(Container);
std::this_thread::sleep_for(2s);
// As example instead of using a Dynamic Library that would get unloaded here
theDataHolder.data.clear();
wait_for_completion(t);
return 0;
}
// INSIDE the SHAERD LIB
std::thread shared_lib_entry(DataContainer &aContainer) {
std::cout << "Entry in the lib: " << private_var << std::endl;
std::thread aThread([&](){
std::cout << "in the thread start" << std::endl;
int count = 5;
while (count-- > 0) {
std::cout << "in the thread ["<< count <<"]" << std::endl;
if (aContainer.m_Data.expired()) {
std::cout << "Someone killed the src " << std::endl;
} else {
auto sp = aContainer.m_Data.lock();
std::cout << "Str: " << sp->SomeStr << std::endl;
}
std::this_thread::sleep_for(1s);
}
});
std::cout << "Thread finished " << private_var << std::endl;
return aThread;
}

最新更新