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

问题描述 投票:0回答:2

目前,我正在使用动态库进行测试,并且在数据管理/删除方面遇到了一些麻烦...我如何“通知”指针其无效?

我需要:线程安全的方法,从其库中删除数据并使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;
}

c++ pointers thread-safety dynamic-library
2个回答
1
投票

shared_ptr / weak_ptr是您需要的。保留所有权的模块具有shared_ptr个对象,但允许其他人仅获取weak_ptr个对象。其他模块(不应该拥有所有权的模块)每次需要数据时都必须临时从shared_ptr中获取weak_ptr,并且它们有义务在访问数据后立即销毁每个shared_ptr。

如果不保留此不变式,则需要在模块之间进行一些外部同步,例如onPointerInvalidated,但这是更糟糕的设计。

关于线程安全,如果您将shared_ptr保留在该对象上,那么任何人都无法销毁该对象(除非有人进行诸如delete shared_ptr_.get()的恶意操作)。这暗示着使用者与所有者之间的契约:使用者在很短的时间内锁定了shared_ptr(因此延迟了销毁(如果有的话)),而所有者删除对象则不用担心任何悬空的指针。


0
投票

我同意,我认为共享/弱指针应该可以解决问题。这就是我的实现方式:

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;
}
© www.soinside.com 2019 - 2024. All rights reserved.