【问题标题】:Unhandled exception exception in boost shared_ptr destructorboost shared_ptr 析构函数中未处理的异常异常
【发布时间】:2014-05-26 06:59:43
【问题描述】:

我的以下代码随机使我的应用程序崩溃,

for(map<_type, boost::shared_ptr<CRowHeaderEx<_type> > >::iterator itr = m_RowMap.begin(); itr != m_RowMap.end(); ++itr)
{
    boost::shared_ptr<CRowHeaderEx<_type> >  pRow = itr->second;
    time_t previoustime = pRow->get_DataReceived();
    if(currenttime - previoustime > Threshold)
    {
        listofdeletedkey.push_back(itr->first);
    }
}

崩溃发生在 shared_ptr 析构函数中的 for 循环的末尾。而且这种崩溃是随机的,不容易重现。

例外: memory.hdmp 中 0x00000752 处未处理的异常:0xC0000005:访问冲突读取位置 0x00000752。

堆栈跟踪:

xxx.exe!boost::detail::sp_counted_base::release() Line 103  C++
xxx.exe!boost::detail::shared_count::~shared_count() Line 309   C++
xxx.exe!boost::shared_ptr<CRowHeaderEx<int> >::~shared_ptr<CRowHeaderEx<int> >()    C++
xxx.exe!CRowManagerEx<int>::PurgeRecords(int Threshold) Line 385    C++

当在 boost::detail::sp_counted_base::release() 中调用 dispose() 函数时,它会崩溃。

void release() // nothrow
{
    if( BOOST_INTERLOCKED_DECREMENT( &use_count_ ) == 0 )
    {
        dispose();
        weak_release();
    }
}

反汇编:

        {
            dispose();
00412B57  mov         edx,dword ptr [this]  
00412B5A  mov         eax,dword ptr [edx]  
00412B5C  mov         ecx,dword ptr [this]  
00412B5F  mov         edx,dword ptr [eax+4]  
00412B62  call        edx  

edx 值在这里是 0x00000752。这导致了访问冲突。

【问题讨论】:

    标签: c++ boost shared-ptr unhandled-exception


    【解决方案1】:

    而且这种崩溃是随机的,不容易重现。

    您的程序遇到某种形式的内存损坏。我相信我之前的帖子对如何在 Windows 平台上使用 WinDBG/Pageheap 识别内存损坏很有帮助。

    https://stackoverflow.com/a/22074401/2724703

    edx 值在这里是 0x00000752。这导致了访问冲突。

    这表明,您正在尝试访问 NULL 指针内存(偏移量为 +1874/0x752 字节)。这可能有几个原因,通过查看您当前的信息无法理解所有原因。其中一个原因可能是您的程序是多线程的,而其他一些线程正试图与该线程同时释放此共享内存。

    编辑

    可以从boost 文档中找到以下信息。

    shared_ptr 对象提供与内置线程安全级别相同的线程安全性 类型。可以“读取” shared_ptr 实例(仅使用 const 访问 操作)同时由多个线程。不同的shared_ptr 实例可以“写入”(使用可变操作访问,例如 作为 operator= 或重置)同时由多个线程(即使当 这些实例是副本,并且共享相同的引用计数 下面。)

    任何其他同时访问都会导致未定义的行为

    【讨论】:

    • 感谢您的回复。该应用程序是多线程的。但是所有对 m_RowMap 的访问都受到临界区的保护。引发异常的代码在智能 ptr 析构函数中。底层对象通过 shared_ptr 访问,并且永远不会在代码中的任何地方直接访问。 shared_ptr 不应该维护引用计数并且只在没有代码引用时删除对象吗?
    • @Krishna:我更新了关于 shared_ptr 线程安全的帖子。您提到所有访问 m_RowMap 变量都受 CS 保护。但是从析构函数中抛出异常表明你的程序中发生了一些严重的事情。好吧,我仍然觉得由于程序的多线程性质正在发生某种内存损坏情况。正如我所提到的,动态工具在这些情况下会很有用。好吧,我对此没有什么要补充的。
    • 我同意这是某种堆损坏。和boost没有关系。我查看了存储在特定内存范围内的行映射条目和对象的值已损坏。现在困难的部分是找出代码的哪一部分正在破坏堆。谢谢你的帮助。
    猜你喜欢
    • 2013-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多