在遗留代码上使用shared_ptr时发生访问冲突

发布于 2024-12-29 10:44:24 字数 1370 浏览 2 评论 0原文

我在旧应用程序中使用shared_ptr等实现了一个新模块,但是当shared_ptr调用析构函数时,我遇到了访问冲突。

app:

case ENUM_DATA:
{
    std::tr1::shared_ptr<CDataMsg> msg(new CDataMsg(_stringmsg)); // _stringmsg is initialized before
    Process(msg);
    break;
}

Process():

bool Process(std::tr1::shared_ptr<CDataMsg> msg)
{
    try
    {
        switch (msg->getDataType())
        {
            case ENUM_MYDATATYPE:
            {
                std::tr1::shared_ptr<CMyData> base(msg->getData());
                std::tr1::shared_ptr<CMyDataChild> data(std::tr1::static_pointer_cast<CMyDataChild>(base));

                // do some stuff with data
                std::tr1::shared_ptr<CRequest> request(new CRequest(data->getParam1(), data->getParam2()));
                handler->AddRequest(request->getBin());
                break;
            }
            default:;
        }
        return true;
    }
    catch (...)
    {
        // exception handling
    }
    return false;
}

析构函数:

CDataMsg::~CDataMsg()
{
    if (m_data)
        delete m_data;
    m_data = NULL;
}

m_data 是一个 CMyData* (此时无法更改)。

CDataMsg 是一个容器,其中保存 CMyData 类型的数据。 CmyDataChild是CMyData的子类,这里使用的是CMyData。

我在析构函数中有断点,但调试器仅在共享指针调用它时停止,然后我已经遇到访问冲突。

I implement a new module using shared_ptr etc. in our legacy app, however I get a access violation, when shared_ptr is calling the destructor.

app:

case ENUM_DATA:
{
    std::tr1::shared_ptr<CDataMsg> msg(new CDataMsg(_stringmsg)); // _stringmsg is initialized before
    Process(msg);
    break;
}

Process():

bool Process(std::tr1::shared_ptr<CDataMsg> msg)
{
    try
    {
        switch (msg->getDataType())
        {
            case ENUM_MYDATATYPE:
            {
                std::tr1::shared_ptr<CMyData> base(msg->getData());
                std::tr1::shared_ptr<CMyDataChild> data(std::tr1::static_pointer_cast<CMyDataChild>(base));

                // do some stuff with data
                std::tr1::shared_ptr<CRequest> request(new CRequest(data->getParam1(), data->getParam2()));
                handler->AddRequest(request->getBin());
                break;
            }
            default:;
        }
        return true;
    }
    catch (...)
    {
        // exception handling
    }
    return false;
}

Destructor:

CDataMsg::~CDataMsg()
{
    if (m_data)
        delete m_data;
    m_data = NULL;
}

m_data is a CMyData* (cannot be changed at this point).

CDataMsg is a container, which holds data of type CMyData. CmyDataChild is a subclass of CMyData, which is used here.

I have breakpoint in the destructor, but the debugger stops only, when shared_ptr is calling it and then I get the access violation already.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

芸娘子的小脾气 2025-01-05 10:44:24

正如您在评论中确认的那样, msg->getData() 返回一个指向 msg 的成员变量的指针(大概是 m_data),并且它当此 switch 块作用域退出时将被删除:

case ENUM_MYDATATYPE:
{
    std::tr1::shared_ptr<CMyData> base(msg->getData());
    std::tr1::shared_ptr<CMyDataChild>
        data(std::tr1::static_pointer_cast<CMyDataChild>(base));

    // do some stuff with data
    std::tr1::shared_ptr<CRequest>
        request(new CRequest(data->getParam1(), data->getParam2()));
    handler->AddRequest(request->getBin());
    break;
}

当此 switch 块作用域退出时,稍后将调用 msg 的析构函数:

case ENUM_DATA:
{
    std::tr1::shared_ptr<CDataMsg> msg(new CDataMsg(_stringmsg));
    Process(msg);
    break;
}

并尝试重新删除成员变量m_data

另外:

case ENUM_MYDATATYPE:
{
    std::tr1::shared_ptr<CMyData> base(msg->getData());
    std::tr1::shared_ptr<CMyDataChild>
        data(std::tr1::static_pointer_cast<CMyDataChild>(base));
    ...
}

data 指向与 base 相同的对象。当此作用域退出时,base 将被删除两次。

As you have confirmed in your comment msg->getData() returns a pointer to a member variable of msg (presumably m_data) and it will be deleted when this switch block scope exits:

case ENUM_MYDATATYPE:
{
    std::tr1::shared_ptr<CMyData> base(msg->getData());
    std::tr1::shared_ptr<CMyDataChild>
        data(std::tr1::static_pointer_cast<CMyDataChild>(base));

    // do some stuff with data
    std::tr1::shared_ptr<CRequest>
        request(new CRequest(data->getParam1(), data->getParam2()));
    handler->AddRequest(request->getBin());
    break;
}

The destructor of msg will be invoked later when this switch block scope exits:

case ENUM_DATA:
{
    std::tr1::shared_ptr<CDataMsg> msg(new CDataMsg(_stringmsg));
    Process(msg);
    break;
}

and attempt to redelete the member variable m_data.

Also:

case ENUM_MYDATATYPE:
{
    std::tr1::shared_ptr<CMyData> base(msg->getData());
    std::tr1::shared_ptr<CMyDataChild>
        data(std::tr1::static_pointer_cast<CMyDataChild>(base));
    ...
}

data is pointing to the same object as base. When this scope exits base will be deleteded twice.

只等公子 2025-01-05 10:44:24

每当我看到这样的错误时,我立即想到双重删除。

std::tr1::shared_ptr<CMyData> base(msg->getData());
if (m_data) delete m_data;  //- in CDataMsg destructor

是否有可能“m_data”被删除两次?一次在shared_ptr中,一次在CDataMsg析构函数中。

Whenever I see bugs like this, I immediately think double delete.

std::tr1::shared_ptr<CMyData> base(msg->getData());
if (m_data) delete m_data;  //- in CDataMsg destructor

Is it possible that 'm_data' is being deleted twice? Once in the shared_ptr and once in the CDataMsg destructor.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文