c ++破坏器混乱,不可能调试 [英] c++ destructor mess, impossible to debug

查看:124
本文介绍了c ++破坏器混乱,不可能调试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我运行我的程序一切都很好。最后打印出来:

when I run my program everything goes fine. At the end it prints out this:

*** glibc detected *** ./streamShare: double free or corruption (fasttop): 0x08292130 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xcc2ff1]
/lib/tls/i686/cmov/libc.so.6[0xcc46f2]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0xcc779d]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0x1c86f1]
./streamShare[0x804be7f]
./streamShare[0x804be3e]
./streamShare[0x804abc0]
./streamShare[0x804a5f2]
./streamShare[0x804a1c4]
./streamShare[0x804a1d7]
./streamShare[0x804a46a]
./streamShare[0x804ba45]
./streamShare[0x804b49c]
./streamShare[0x804ac68]
./streamShare[0x804ac48]
./streamShare[0x804a676]
./streamShare[0x804a237]
./streamShare[0x8049a3f]
./streamShare[0x804d2e5]
./streamShare[0x804d34d]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0xc6eb56]
./streamShare[0x8049361]

我检出,一个函数返回,其中程序的所有对象都自动安装。反正我没有为这些对象定义任何析构函数,我试图使用STL容器和TR1 shared_ptr。我想一切发生在默认析构函数。有没有办法知道它在哪里分手?我的意思是,我想知道哪个对象破坏了整个混乱。我使用这些容器和共享指针:

I checked out, it happens when a function returns, where all the objects of the program are instatied automatically. Anyway I didn't define any destructor for these objects, I tried to use STL Containers and TR1 shared_ptr. I guess everything happens in the default destructors. Is there a way to know where does it breaks up? I mean, I'd like to know which object distruction does the whole mess. I'm using these containers and shared pointers:

typedef std::tr1::shared_ptr<messageListener> mlsptr;

typedef std::map<const char*, mlsptr, ltstr> CONSTCHP2MSLST;

messageListener没有分解。和这些向量中的两个:

messageListener doesn't have a distructor. And two of these vectors:

std::vector<MSG> queueto1;

其中MSG析构函数为:

where MSG destructor is:

MSG::~MSG() {
    destroy();
}

void MSG::destroy() {
    if (payload != NULL)
    	delete[] payload;
    payload = NULL;
    payloadLen = 0;
}

任何推荐如何跟踪此问题?我没有...

Any recomendations how to track this problem? I'm clueless...

编辑:

这是有效的输出:

valgrind ./streamShare -v
==25795== Memcheck, a memory error detector
==25795== Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.
==25795== Using Valgrind-3.5.0-Debian and LibVEX; rerun with -h for copyright info
==25795== Command: ./streamShare -v
==25795== 
==25795== Invalid free() / delete / delete[]
==25795==    at 0x402454D: operator delete(void*) (vg_replace_malloc.c:346)
==25795==    by 0x804BCC0: std::tr1::_Sp_deleter<streamShare::messageListener>::operator()(streamShare::messageListener*) const (shared_ptr.h:97)
==25795==    by 0x804BC7F: std::tr1::_Sp_counted_base_impl<streamShare::messageListener*, std::tr1::_Sp_deleter<streamShare::messageListener>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr.h:75)
==25795==    by 0x804AAF7: std::tr1::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (boost_sp_counted_base.h:140)
==25795==    by 0x804A58D: std::tr1::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr.h:153)
==25795==    by 0x804A173: std::tr1::__shared_ptr<streamShare::messageListener, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr.h:358)
==25795==    by 0x804A186: std::tr1::shared_ptr<streamShare::messageListener>::~shared_ptr() (shared_ptr.h:834)
==25795==    by 0x804A405: std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >::~pair() (stl_pair.h:68)
==25795==    by 0x804D3D0: __gnu_cxx::new_allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >::destroy(std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >*) (new_allocator.h:115)
==25795==    by 0x804D337: std::_Rb_tree<char const*, std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >, std::_Select1st<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >, streamShare::ltstr, std::allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >*) (stl_tree.h:383)
==25795==    by 0x804D29B: std::_Rb_tree<char const*, std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >, std::_Select1st<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >, streamShare::ltstr, std::allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > > >::_M_erase(std::_Rb_tree_node<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >*) (stl_tree.h:972)
==25795==    by 0x804D27B: std::_Rb_tree<char const*, std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >, std::_Select1st<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >, streamShare::ltstr, std::allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > > >::_M_erase(std::_Rb_tree_node<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >*) (stl_tree.h:970)
==25795==  Address 0x42c3358 is 0 bytes inside a block of size 8 free'd
==25795==    at 0x402454D: operator delete(void*) (vg_replace_malloc.c:346)
==25795==    by 0x804BCC0: std::tr1::_Sp_deleter<streamShare::messageListener>::operator()(streamShare::messageListener*) const (shared_ptr.h:97)
==25795==    by 0x804BC7F: std::tr1::_Sp_counted_base_impl<streamShare::messageListener*, std::tr1::_Sp_deleter<streamShare::messageListener>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr.h:75)
==25795==    by 0x804AAF7: std::tr1::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (boost_sp_counted_base.h:140)
==25795==    by 0x804A58D: std::tr1::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr.h:153)
==25795==    by 0x804A173: std::tr1::__shared_ptr<streamShare::messageListener, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr.h:358)
==25795==    by 0x804A186: std::tr1::shared_ptr<streamShare::messageListener>::~shared_ptr() (shared_ptr.h:834)
==25795==    by 0x804A405: std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >::~pair() (stl_pair.h:68)
==25795==    by 0x804D3D0: __gnu_cxx::new_allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >::destroy(std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >*) (new_allocator.h:115)
==25795==    by 0x804D337: std::_Rb_tree<char const*, std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >, std::_Select1st<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >, streamShare::ltstr, std::allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > > >::_M_destroy_node(std::_Rb_tree_node<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >*) (stl_tree.h:383)
==25795==    by 0x804D29B: std::_Rb_tree<char const*, std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >, std::_Select1st<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >, streamShare::ltstr, std::allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > > >::_M_erase(std::_Rb_tree_node<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >*) (stl_tree.h:972)
==25795==    by 0x804D27B: std::_Rb_tree<char const*, std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> >, std::_Select1st<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >, streamShare::ltstr, std::allocator<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > > >::_M_erase(std::_Rb_tree_node<std::pair<char const* const, std::tr1::shared_ptr<streamShare::messageListener> > >*) (stl_tree.h:970)
==25795== 
==25795== 
==25795== HEAP SUMMARY:
==25795==     in use at exit: 0 bytes in 0 blocks
==25795==   total heap usage: 22 allocs, 30 frees, 496 bytes allocated
==25795== 
==25795== All heap blocks were freed -- no leaks are possible
==25795== 
==25795== For counts of detected and suppressed errors, rerun with: -v
==25795== ERROR SUMMARY: 8 errors from 1 contexts (suppressed: 19 from 8)


推荐答案

根据Valgrind输出判断,问题是一个 shared_ptr 指向的对象被删除两次。得到的一个可能性是,如果你用相同的原始指针初始化两个 shared_ptr ,例如:

Judging by your Valgrind output, the problem is that an object pointed to by a shared_ptr is being deleted twice. One possibility of getting that is if you initialize two shared_ptr with the same raw pointer, e.g.:

int* p = new int(123);
shared_ptr<int> sp1(p);
shared_ptr<int> sp2(p);

shared_ptr 不是神奇的,知道如果你要求它照顾的对象已经拥有一些其他不相关的 shared_ptr ,如果你给它是一个原始指针。在上面的例子中,每个 shared_ptr 将创建自己的引用计数器,初始化为1;当它们死亡时,每个都会递减自己的计数器,看到它为0,并删除对象,产生双重删除。我怀疑你的情况是类似的。如果显示用于初始化添加到向量中的 shared_ptr 对象的代码,则可以验证此代码。

shared_ptr is not magical, and it cannot know if the object you ask it to take care of is already owned by some other unrelated shared_ptr, if all you give it is a raw pointer. In the example above, each shared_ptr will create its own reference counter, initialized to 1; when they die, each will decrement its own counter, see that it is 0, and delete the object, producing double deletion. I suspect your case is similar. If you show the code used to initialize shared_ptr objects that are added to the vector, this can be verified.

由于这已验证为当前崩溃的原因,请让我详细说明一个
位如何正确使用 shared_ptr

Since this is validated to be the cause of the crash now, let me elaborate a bit on how to properly use shared_ptr.

首先,问题的性质。写入 shared_ptr 的方式,它适用于任何C ++类型,并提供引用计数语义。显而易见的问题是大多数类型不提供任何空间来存储引用计数器(例如考虑 shared_ptr - $内没有额外的空间code > int )。要解决这个问题,对于每个共享对象,将分配一个单独的内存块,其中包含引用计数器。每当你从一个原始指针创建一个 shared_ptr 时,这样做。然后, shared_ptr 对象本身存储原始指针,以及指向引用计数器的指针(这就是为什么它比原始指针更胖的原因, sizeof )。当您从另一个(使用复制构造函数或赋值运算符)创建一个 shared_ptr 时,它将指针复制到引用计数器,因此所有 shared_ptr 从彼此创建的实例维护单个计数器,并保证正确删除。但是如果你有两个不相关的家族的 shared_ptr 对象到同一对象(其中两个或更多的指针是从相同的原始指针创建的),那些家庭

First of all, the nature of the problem. The way shared_ptr is written, it works with any C++ type, and provides reference counting semantics. The obvious problem is that most types do not provide any space to store the reference counter (e.g. consider shared_ptr<int> - there's no extra space "inside" int). To work around this, for every shared object, a separate block of memory is allocated that contains the reference counter. This is done whenever you create a shared_ptr from a raw pointer. The shared_ptr object itself then stores the original raw pointer, and the pointer to reference counter (which is why it's more "fat" than a raw pointer, which can be trivially checked with sizeof). When you create one shared_ptr from another (using copy constructor or assignment operator), it copies the pointer to reference counter, so all shared_ptr instances created from one another maintain a single counter, and guarantee correct deletion. But if you have two unrelated "families" of shared_ptr objects to the same objects (where two or more pointers were created from the same raw pointer), those "families" do not know about each other, and will refcount separately, and each will delete when it hits 0.

在实践中,这意味着,当使用时, shared_ptr ,必须遵守某些规则。

What this means in practice is that, when using shared_ptr, one must adhere to certain rules. Those depend on which implementation you use.

使用 std :: tr1 :: shared_ptr 或旧的Boost版本,对象分配的唯一完全安全模式是:

With std::tr1::shared_ptr, or older Boost versions, the only fully safe pattern for object allocation is this:

shared_ptr<T> x(new T(...));

换句话说, new 应立即放入 shared_ptr - 然后可以根据需要复制后者。

In other words, the result of new should be immediately put into a shared_ptr - you can then copy the latter as much as you want.

一个相当安全的模式也是这样:

A reasonably safe pattern is also this:

auto_ptr<T> x(new T);
...
shared_ptr<T> y(x);

shared_ptr auto_ptr 初始化时的所有权以及后者的语义(只要它们被正确遵循)确保只有一个 auto_ptr 到一个对象应该存在;因此,从中构造一个 shared_ptr 是安全的。

shared_ptr implements the usual transfer-of-ownership when initializing from auto_ptr, and the semantics of the latter (so long as they're correctly followed) ensure that only one auto_ptr to an object should exist; thus, it is safe to construct a shared_ptr from that.

有时你还必须处理C ++库不要使用 auto_ptr 来指示指针所有权的转移,而只是记录特定函数的意图。在这些情况下,使用 shared_ptr 也应该是安全的,但是您当然应该确保您已正确理解文档...

Sometimes you also have to deal with C++ libraries which do not use auto_ptr to indicate transfer of pointer ownership, but simply document the intent for specific functions. In those cases it should also be safe to use shared_ptr, but of course you should be sure that you've understood the documentation correctly...

在C ++ 0x std :: shared_ptr 中,在较新版本的 boost :: shared_ptr ,提供了助手以确保共享对象的正确实例化:

In C++0x std::shared_ptr, and in newer versions of boost::shared_ptr, there's a helper provided to ensure correct instantiation of shared objects:

shared_ptr<int> p = make_shared<int>(123);

make_shared< T>()的返回类型已经是 shared_ptr< T> ,所以你在处理代码中的原始指针,减少错误的机会。

The return type of make_shared<T>() is already shared_ptr<T>, so at no point you're dealing with raw pointers in your code, reducing chance to get something wrong.

这篇关于c ++破坏器混乱,不可能调试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆