Why the destrcution is called twice? - c++

I have got one crash. and I use gdb to analyze the stack,I got the below result.
13 0x00007f423c6e9670 in ?? ()
#14 0x00007f42340496d8 in ?? ()
#15 0x0000000003cef568 in ?? ()
#16 0x00000000008da861 in HuffmanEnd ()
#17 0x00000000008d4a83 in faacEncClose ()
#18 0x00000000004fd797 in RecorderSession::~RecorderSession (this=0x7f423404ea90, __in_chrg=<value optimized out>)
at /root/Desktop/VideoRecoder/2.0/src/videorecorder/RecorderSession.cpp:203
#19 0x00000000004fdae9 in RecorderSession::~RecorderSession (this=0x7f423404ea90, __in_chrg=<value optimized out>)
at /root/Desktop/VideoRecoder/2.0/src/videorecorder/RecorderSession.cpp:203
#20 0x0000000000500d0b in RecorderSession::OnHangup (this=0x7f423404ea90) at /root/Desktop/VideoRecoder/2.0/src/videorecorder/RecorderSession.cpp:295
#21 0x000000000045e083 in CSipPhone::on_call_state (call_id=2, e=<value optimized out>)
As we see, the crash happens in the HuffmanEnd. But I don't understand why the ~RecorderSession is called twice although I use code "delete this" to delete the RecorderSession object as below:
int RecorderSession::OnHangup()
{
delete this;
return 0;
}
So does the "delete this" cause this phenomenon?

The chances are that your function OnHangup itself is already being called from the destructor of the object in question. Thus you are calling delete on yourself when the object is already in the middle of being destroyed, causing the double delete.

It seems your object is created by placement new, or as a local object on the stack, or as a namespace-scope / global, or as a member of another object.
In that case Dtor will be called one more time.

Related

Strange behaviour with std::unique_ptr and std::ostringstream (SIGSEGV)

I am currently trying to wrap an std::ostringstream into and std::unique_ptr.
My current code compiles, but at runtime, I am getting an segmentation fault.
When I do not wrap it - using an old c-style pointer, it runs fine.
For a more detailed overview, I am downloading data using curlpp into an ostringstream.
This is what I am doing:
std::unique_ptr< std::ostringstream > data_stream;
curlpp::Cleanup myCleanup;
*data_stream << curlpp::options::Url(this->m_ressource_url);
The segmentation fault occurs at the last line, this is the backtrace:
0x00007ffff790e2ce in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/libstdc++.so.6
(gdb) bt
#0 0x00007ffff790e2ce in std::ostream::sentry::sentry(std::ostream&) () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/libstdc++.so.6
#1 0x00007ffff790e3f7 in std::ostream::write(char const*, long) () from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/libstdc++.so.6
#2 0x0000000000429be6 in curlpp::internal::Callbacks::StreamWriteCallback (buffer=0x660d1b "Das ist (k)ein Test.", size=1, nitems=20, stream=0x0)
at OptionSetter.cpp:55
#3 0x00007ffff7b90678 in ?? () from /usr/lib64/libcurl.so.4
#4 0x00007ffff7ba4d38 in ?? () from /usr/lib64/libcurl.so.4
#5 0x00007ffff7bac967 in ?? () from /usr/lib64/libcurl.so.4
#6 0x00007ffff7bad5e5 in curl_multi_perform () from /usr/lib64/libcurl.so.4
#7 0x00007ffff7ba5dd6 in curl_easy_perform () from /usr/lib64/libcurl.so.4
#8 0x0000000000425a78 in curlpp::internal::CurlHandle::perform (this=0x6690b0) at CurlHandle.cpp:52
#9 0x0000000000424fca in curlpp::Easy::perform (this=0x7fffffffd5c0) at Easy.cpp:48
#10 0x00000000004252ba in operator<< (stream=..., request=...) at Easy.cpp:116
#11 0x0000000000424d7f in operator<< (stream=..., url=...) at Options.cpp:34
#12 0x0000000000420bb1 in Model<std::string>::m_download (this=0x7fffffffd878)
at /home/bueddl/Developement/Studium/Semester 4/SWT/Source/model/src/Model.hpp:98
#13 0x0000000000420a4e in Model<std::string>::refresh (this=0x7fffffffd878)
at /home/bueddl/Developement/Studium/Semester 4/SWT/Source/model/src/Model.hpp:71
#14 0x00000000004206a5 in main () at /home/bueddl/Developement/Studium/Semester 4/SWT/Source/model/src/main.cpp:56
FYI, my files are from #14 to #12, the code above is a part of the file #12.
Now, this is strange, when I am writing the fallowing code, it works without problems:
std::ostringstream *data_stream = new std::ostringstream();
curlpp::Cleanup myCleanup;
*data_stream << curlpp::options::Url(this->m_ressource_url);
Both cases are passing pointers to the operator<<, but I seem to be wrong.
Where am I wrong?
Thanks for your help :)
Note: I wanted to use the unique_ptr for implementing sink-source pattern.
unique_ptr doesn't automatically create an instance of the pointed to object. You still need to do that yourself. So your code is trying to use a NULL pointer to a stream.
You need to do something like:
std::unique_ptr< std::ostringstream > data_stream(new std::ostringstream);
curlpp::Cleanup myCleanup;
*data_stream << curlpp::options::Url(this->m_ressource_url);

Why is my program crashing in boost::enable_shared_from_this<>/boost::shared_ptr<>?

I'm trying to hunt down why a program is crashing in shared_ptr.
#0 0x00007fff90723212 in __pthread_kill ()
#1 0x00007fff93415b54 in pthread_kill ()
#2 0x00007fff93459dce in abort ()
#3 0x00007fff8a0519eb in abort_message ()
#4 0x00007fff8a04f39a in default_terminate ()
#5 0x00007fff930bf887 in _objc_terminate ()
#6 0x00007fff8a04f3c9 in safe_handler_caller ()
#7 0x00007fff8a04f424 in std::terminate ()
#8 0x00007fff8a05058b in __cxa_throw ()
#9 0x0000000100057cbc in boost::throw_exception<boost::bad_weak_ptr> (e=#0x1002c5b88) at throw_exception.hpp:66
#10 0x0000000100057bf4 in boost::detail::shared_count::shared_count (this=0x1002c5d00, r=#0x100304180) at shared_count.hpp:509
#11 0x0000000100057b7d in boost::detail::shared_count::shared_count (this=0x1002c5d00, r=#0x100304180) at shared_count.hpp:511
#12 0x000000010004ad14 in boost::shared_ptr<myns::(anonymous namespace)::MySharedFromThisClass>::shared_ptr<myns::(anonymous namespace)::MySharedFromThisClass> (this=0x1002c5cf8, r=#0x100304178) at shared_ptr.hpp:220
#13 0x000000010004acad in boost::shared_ptr<myns::(anonymous namespace)::MySharedFromThisClass>::shared_ptr<myns::(anonymous namespace)::MySharedFromThisClass> (this=0x1002c5cf8, r=#0x100304178) at shared_ptr.hpp:223
#14 0x000000010004a9b4 in boost::enable_shared_from_this<myns::(anonymous namespace)::MySharedFromThisClass>::shared_from_this (this=0x100304178) at enable_shared_from_this.hpp:49
MySharedFromThisClass is defined as:
class MySharedFromThis : public boost::enable_shared_from_this<MySharedFromThis> {
// ....
};
And the instance that was being passed around was defined like:
auto myKlass = std::make_shared<MySharedFromThis>();
And being copied around via:
void myFunction(::boost::shared_ptr<MySharedFromThis> myKlass) {
myFunction(shared_from_this());
}
What gives? Everything compiles with no warnings or errors, but things very clearly segfault in not so pleasant ways.
I'm posting my own answer because this chunk of code compiled without any warnings or errors and took a fair amount of effort to track down.
It should be pretty obvious based on the example above when looking at this line:
auto myKlass = std::make_shared<MySharedFromThis>();
myKlass is of type std::shared_ptr<MySharedFromThis>, not boost::shared_ptr<MySharedFromThis>. Change std::make_shared<> to boost::make_shared<> and everything works as expected/intended.
There are two possible things leading to this crash:
The call to shared_from_this() in myFunction() was being called without an existing ::boost::shared_ptr<> already existing. Instead, what had happened was a std::shared_ptr<> was created, which has a different ABI that a boost::shared_ptr<>. Notably a libboost_thread-mt.dylib expects a boost::enable_shared_from_this<> class and not a std::enable_shared_from_this<> class.
According to the enable_shared_from_this<> documentation, the prerequisite was not satisfied.
Requires: enable_shared_from_this must be an accessible base class of T. *this must be a subobject of an instance t of type T . There must exist at least one shared_ptr instance p that owns t.
Instead what had happened was there was a std::shared_ptr<> instance, but not a boost::shared_ptr<> instance.
At least that's my understanding of what was going on. I think #1 is the real problem leading to the segfault, and #2 would have been a problem sooner or later (though I'm not entirely convinced).

Why is the destructor called twice for the same object?

In the following backtrace from a core dump A2:~A2 is called twice:
#0 0x086f5371 in B1::~B1 (this=0xe6d3a030,
__in_chrg=<value optimized out>)
at /fullpath/b1.cpp:400
#1 0x086ffd43 in ~B2 (this=0xe6d3a030,
__in_chrg=<value optimized out>)
at /fullpath/b2.h:21
#2 B2::~B2 (this=0xe6d3a030,
__in_chrg=<value optimized out>)
at /fullpath/b2.h:21
#3 0x086ea516 in A1::~A1 (this=0xe3e93958,
__in_chrg=<value optimized out>)
at /fullpath/a1.cpp:716
#4 0x0889b85d in A2::~A2 (this=0xe3e93958,
__in_chrg=<value optimized out>)
at /fullpath/a2.cpp:216
#5 0x0889b893 in A2::~A2 (this=0xe3e93958,
__in_chrg=<value optimized out>)
at /fullpath/a2.cpp:216
#6 0x0862c0f1 in E::Identify (this=0xe8083e20, t=PT_UNKNOWN)
at /fullpath/e.cpp:713
A2 is derived from A1 and B2 is derived from B1. Only B2 has a default destructor, all base class destructors are virtual.
The code looks something like this:
e.cpp:
E::E(){
//... some code ...
myA1= new A2();
}
void E::Identify(){
//...
if(myA1){
delete myA1; //line 713 of e.cpp
myA1 = NULL;
}
}
a2.cpp:
A2::~A2(){
//...
if (sd) //sd is not null here and also not made null after deletion
{
delete [] sd; //when called the second time shouldn't it crash here?
}
//...
} // line 216 of a2.cpp
a1.cpp
A1::A1(){
//...
myB1 = new B2();
//...
}
A1::~A1(){
//...
delete myB1; //line 716 of a1.cpp
//...
}
I cannot understand why A2::~A2 is called twice for the same object ( the this pointer in the backtrace has the same value for both 4 and 5 frames).
If I go to frame 4 and disassemble it prints a very different result from the frame 5 disassembeled code (about 90 lines of assembly code vs about 20 lines of assembly code).
I minimalized the example to
#include <cassert>
class A1 {
public:
virtual ~A1() {
assert(false);
}
};
class A2 : public A1 {
};
int main() {
A1* a = new A2;
delete a;
return 0;
}
with the assert to trigger a core dump.
Compiling with g++ 4.7.2, we get the double destructor backtrace in gdb
#0 0x00007f16060e92c5 in raise () from /usr/lib/libc.so.6
#1 0x00007f16060ea748 in abort () from /usr/lib/libc.so.6
#2 0x00007f16060e2312 in __assert_fail_base () from /usr/lib/libc.so.6
#3 0x00007f16060e23c2 in __assert_fail () from /usr/lib/libc.so.6
#4 0x00000000004007c8 in A1::~A1 (this=0xf60010, __in_chrg=<optimized out>) at double.cpp:6
#5 0x000000000040084d in A2::~A2 (this=0xf60010, __in_chrg=<optimized out>) at double.cpp:10
#6 0x0000000000400880 in A2::~A2 (this=0xf60010, __in_chrg=<optimized out>) at double.cpp:10
#7 0x000000000040078c in main () at double.cpp:15
while the backtrace of the same code compiled with g++ 4.3.2 looks similar but with only one frame for A2::~A2.
Both backtraces extracted with the same version of gdb (7.5.1).
So it is an artifact of the code generated by g++ 4.7, nothing to worry about for the behaviour of the compiled binary. It is not a real double call to the destructor.
This could be your scenario (but you didn't show us this part of the code)...
If class E holds a private member pointer to A2, and it doesn't have a copy constructor or operator= ....
Then, there could be a situation where an Object of type E is copied to another object (variable) of type E with the default copy constructor or operator =.
That will cause shallow copying of members, which will cause both objects to now point to the same object A1.
When the object E's are destroyed, they both try to delete the same A2 object.

Trouble diagnosing segfault in Qt application

I have an application using QtWebKit. It loads URLs and exports some stats on the render trees. This section of code is causing problems:
...
if (mPage != 0) {
disconnectSignals(mPage);
delete mPage;
}
mPage = new Page(); //subclass of QWebPage
connectSignals(mPage);
QNetworkRequest req;
req.setUrl("http://...");
mPage->mainFrame()->load(req, QNetworkAccessManager::GetOperation);
The first time the above code runs mPage=0, the page loads fine, and everything else goes as expected. The second time, it's a pointer to the previously created page, so it gets disconnected and deleted. After load() returns control to the main event loop, I get a SIGSEGV with the following stack trace.
#0 0x00007ffff49a1e56 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#1 0x00007ffff6842972 in QWebFrame::loadFinished(bool) () from /home/ubuntu/3rdparty/qt- 4.8.1/lib/libQtWebKit.so.4
#2 0x00007ffff6881955 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#3 0x00007ffff6bde3ab in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#4 0x00007ffff6c0ef14 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#5 0x00007ffff6e0183b in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#6 0x00007ffff6e016e8 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#7 0x00007ffff6e01755 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#8 0x00007ffff6e0218c in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtWebKit.so.4
#9 0x00007ffff49a20c1 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#10 0x00007ffff4d72b46 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtNetwork.so.4
#11 0x00007ffff4de91c5 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtNetwork.so.4
#12 0x00007ffff49a7286 in QObject::event(QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#13 0x00007ffff5243fa4 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtGui.so.4
#14 0x00007ffff5248e23 in QApplication::notify(QObject*, QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtGui.so.4
#15 0x00007ffff498e21c in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#16 0x00007ffff4991aba in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#17 0x00007ffff49bce53 in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#18 0x00007ffff235ba5d in g_main_context_dispatch () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#19 0x00007ffff235c258 in ?? () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#20 0x00007ffff235c429 in g_main_context_iteration () from /lib/x86_64-linux-gnu/libglib-2.0.so.0
#21 0x00007ffff49bd27f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#22 0x00007ffff52e78ae in ?? () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtGui.so.4
#23 0x00007ffff498d002 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#24 0x00007ffff498d257 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from / home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#25 0x00007ffff4991db5 in QCoreApplication::exec() () from /home/ubuntu/3rdparty/qt-4.8.1/lib/libQtCore.so.4
#26 0x0000000000408ba0 in main (argc=3, argv=<optimized out>) at RenderTreeAnalyzer.cpp:474
You have to schedule mPage for deletion with deleteLater rather than deleting it directly because there may well be undelivered events for your mPage in the event queue.
If control returns to the event loop, Qt tries to access the deleted object which leads to your segmentation fault.
However, from you code example, I did not fully understand why you need the newPage() signal.
From my understanding, mPage->deleteLater() should be sufficient (w.r.t. to avoiding the seg-fault) and you should be able to reassign your local/member variable mPage with a new value (i.e. a pointer to a new Page) immediately.
If you need the old Page to be deleted immediately, it is correct that you need to return to the event loop, because it is only deleted then.
You have several opportunities to trigger the event loop and get you deletion request processed:
Use your queued signal/slot setup
Call QApplication::processEvents(); after calling mPage->deleteLater() to process any events in the event queue.
Call QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete); to only process all deferred deletions.
Call QCoreApplication::sendPostedEvents(mPage, QEvent::DeferredDelete); to only process the deferred deletion for mPage.
Disclaimer: I have not explicitly tried these suggesions (at least not recently that I remember), but I checked a lot of Qt's event management source code recently (in addition to the docs, of course), so I am pretty confident that all of them work.
The issue was delete mPage;. I have to use mPage->deleteLater(); emit getNext(); instead. deleteLater() schedules the object for deletion the next time the program returns to the main event loop. emit getNext(); is connected to a slot that picks back up at mPage = new Page();. Its connection type is Qt::QueuedConnection, so it will yield to the event loop before calling the slot. I'm not exactly sure why, but you have to schedule the deletion and return to the event loop like this to properly close the old signals and set up the new ones.
So, this works, but if someone can tell me what's going on in more detail, I'll accept yours instead. Thanks.

What could cause a dynamic_cast to crash?

I have a piece of code looking like this :
TAxis *axis = 0;
if (dynamic_cast<MonitorObjectH1C*>(obj))
axis = (dynamic_cast<MonitorObjectH1C*>(obj))->GetXaxis();
Sometimes it crashes :
Thread 1 (Thread -1208658240 (LWP 11400)):
#0 0x0019e7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1 0x048c67fb in __waitpid_nocancel () from /lib/tls/libc.so.6
#2 0x04870649 in do_system () from /lib/tls/libc.so.6
#3 0x048709c1 in system () from /lib/tls/libc.so.6
#4 0x001848bd in system () from /lib/tls/libpthread.so.0
#5 0x0117a5bb in TUnixSystem::Exec () from /opt/root/lib/libCore.so.5.21
#6 0x01180045 in TUnixSystem::StackTrace () from /opt/root/lib/libCore.so.5.21
#7 0x0117cc8a in TUnixSystem::DispatchSignals ()
from /opt/root/lib/libCore.so.5.21
#8 0x0117cd18 in SigHandler () from /opt/root/lib/libCore.so.5.21
#9 0x0117bf5d in sighandler () from /opt/root/lib/libCore.so.5.21
#10 <signal handler called>
#11 0x0533ddf4 in __dynamic_cast () from /usr/lib/libstdc++.so.6
I have no clue why it crashes. obj is not null (and if it was it would not be a problem, would it ?).
What could be the reason for a dynamic cast to crash ?
If it can't cast, it should just return NULL no ?
Some possible reasons for the crash:
obj points to an object with a non-polymorphic type (a class or struct with no virtual methods, or a fundamental type).
obj points to an object that has been freed.
obj points to unmapped memory, or memory that has been mapped in such a way as to generate an exception when accessed (such as a guard page or inaccessible page).
obj points to an object with a polymorphic type, but that type was defined in an external library that was compiled with RTTI disabled.
Not all of these problems necessarily cause a crash in all situations.
I suggest using a different syntax for this code snippet.
if (MonitorObjectH1C* monitorObject = dynamic_cast<MonitorObjectH1C*>(obj))
{
axis = monitorObject->GetXaxis();
}
You can still crash if some other thread is deleting what monitorObject points to or if obj is crazy garbage, but at least your problem isn't casting related anymore and you're not doing the dynamic_cast twice.
As it crashes only sometimes, i bet it's a threading issue. Check all references to 'obj':
grep -R 'obj.*=' .
dynamic_cast will return 0 if the cast fails and you are casting to a pointer, which is your case. The problem is that you have either corrupted the heap earlier in your code, or rtti wasn't enabled.
Are you sure that the value of 'obj' has been correctly defined?
If for example it is uninitialised (ie random) them I could see it causing a crash.
Can the value of obj be changed by a different thread?