Getting a `free()` error when deallocating with `delete` in the backtrace - c++

I got the following error from gdb:
*** glibc detected *** /.root0/autohome/u132/hsreekum/ipopt/ipopt/debug/Ipopt/examples/ex3/ex3: free(): invalid next size (fast): 0x0000000120052b60 ***
Here's the backtrace:
#0 0x000000555626b264 in raise () from /lib/libc.so.6
#1 0x000000555626cc6c in abort () from /lib/libc.so.6
#2 0x00000055562a7b9c in __libc_message () from /lib/libc.so.6
#3 0x00000055562aeabc in malloc_printerr () from /lib/libc.so.6
#4 0x00000055562b036c in free () from /lib/libc.so.6
#5 0x000000555561ddd0 in Ipopt::TNLPAdapter::~TNLPAdapter ()
from /home/ba01/u132/hsreekum/ipopt/ipopt/build/lib/libipopt.so.1
#6 0x00000055556a9910 in Ipopt::GradientScaling::~GradientScaling ()
from /home/ba01/u132/hsreekum/ipopt/ipopt/build/lib/libipopt.so.1
#7 0x00000055557241b8 in Ipopt::OrigIpoptNLP::~OrigIpoptNLP ()
from /home/ba01/u132/hsreekum/ipopt/ipopt/build/lib/libipopt.so.1
#8 0x00000055556ae7f0 in Ipopt::IpoptAlgorithm::~IpoptAlgorithm ()
from /home/ba01/u132/hsreekum/ipopt/ipopt/build/lib/libipopt.so.1
#9 0x0000005555602278 in Ipopt::IpoptApplication::~IpoptApplication ()
from /home/ba01/u132/hsreekum/ipopt/ipopt/build/lib/libipopt.so.1
#10 0x0000005555614428 in FreeIpoptProblem ()
from /home/ba01/u132/hsreekum/ipopt/ipopt/build/lib/libipopt.so.1
#11 0x0000000120001610 in main () at ex3.c:169`
And here's the code for Ipopt::TNLPAdapter::~TNLPAdapter ()
TNLPAdapter::~TNLPAdapter()
{
delete [] full_x_;
delete [] full_lambda_;
delete [] full_g_;
delete [] jac_g_;
delete [] c_rhs_;
delete [] jac_idx_map_;
delete [] h_idx_map_;
delete [] x_fixed_map_;
delete [] findiff_jac_ia_;
delete [] findiff_jac_ja_;
delete [] findiff_jac_postriplet_;
delete [] findiff_x_l_;
delete [] findiff_x_u_;
}
My question is : why does free() throw an error when ~TNLPAdapter() uses delete[]? Also, I would like to step through ~TNLPAdapter() so I can see which deallocation causes the error. I believe the error occurs in the external library (IPOPT) but I have compiled it with debug flags on ; is this sufficient?

Raw memory allocation/deallocation mechanism behind new[]/delete[] is typically the same as the one used by malloc/free. Standard library implementation of raw memory allocation/deallocation functions operator new[]/operator delete[] can actually directly call malloc and free. For this reason, it is completely unsurprising that the error is reported by free even if you are using delete [].
The error that you are getting indicates that the integrity of heap is violated. The heap is broken. The source of the problem can be in this function (double free?) or in some completely different place (double free or memory overrun?). There's no way to say what is happening from the code you posted.
Figure out which specific call to delete [] reports the problem and see if some other code overrides that memory block. Or just use some external tool like valgrind to catch the offender.

Related

Why the destrcution is called twice?

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.

Munmap_chunk() error, cannot understand pointer behavior

I am making a simple sorting program with templates and are struggling with string case.
Code:
template<typename typ>
void Join_Segments(typ *tab, int begin1, int begin2, int end2, bool(*Compare)(typ arg1, typ arg2)){
typ *joined = new typ[end2-begin1+1]; // sorted elements arrray
int c1, c2, ci; // counters
for(c1=begin1, c2=begin2, ci=0; c1<begin2 && c2<=end2; ci++){
if(!Compare(tab[c1], tab[c2])){ joined[ci]=tab[c2]; c2++;}
else{ joined[ci]=tab[c1]; c1++;}
}
while(c1<begin2){joined[ci]=tab[c1]; c1++; ci++;}
while(!(c2>end2)){joined[ci]=tab[c2]; c2++; ci++;}
for(int i=0; i<(end2-begin1+1); i++) tab[begin1+i]=joined[i];
delete joined;
}
So this is working wonderful for integers. And it is working for strings as long as I remove the "delete joined" line, but that is pretty crucial for sorting large arrays.
GDB backtrace log:
Program terminated with signal SIGABRT, Aborted.
#0 0x40022424 in __kernel_vsyscall ()
(gdb) bt
#0 0x40022424 in __kernel_vsyscall ()
#1 0x40171827 in __GI_raise (sig=sig#entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56
#2 0x40174c53 in __GI_abort () at abort.c:89
#3 0x401ac993 in __libc_message (do_abort=do_abort#entry=1,
fmt=fmt#entry=0x402a9a5c "*** Error in `%s': %s: 0x%s ***\n")
at ../sysdeps/posix/libc_fatal.c:175
#4 0x401b6e7a in malloc_printerr (action=<optimized out>,
str=0x402a9a80 "munmap_chunk(): invalid pointer", ptr=0x90551d4)
at malloc.c:4996
#5 0x401b6f48 in munmap_chunk (p=<optimized out>) at malloc.c:2816
#6 0x400849df in operator delete(void*) ()
from /usr/lib/i386-linux-gnu/libstdc++.so.6
#7 0x08049518 in Join_Segments<std::string> (tab=0x905500c, begin1=0, begin2=2,
end2=2, Compare=0x80490a6 <_GLOBAL__sub_I__Z2Nli()+8>) at scalanie.hh:11
#8 0x080491f5 in Mergesort<std::string> (tab=0x905500c, begin=0,
end=2, Compare=0x80490a6 <_GLOBAL__sub_I__Z2Nli()+8>) at scalanie.hh:32
#9 0x08048ee1 in main () at main.cpp:11
I think this is probably caused by std::string assignment magic but I can't figure out how to fix it. Tried a lot of things like casting right hand side of assigment to (const typ&) so it will copy it according to that documentation but it's still trying blindly. Could anyone help me with this?
I can provide full code but it's not visually identical (english is not my native language and I changed functions/var names here) so it may be harder to read.
Thanks!
You should use delete[] since you are deleting an array allocated with new[]. Mixing incorrect types of new/delete can lead to undefined behavior according to the standard which I guess is what you are seeing.

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);

New operator crash

I have a crash with signal 6 aborted on new operator with the following callstack:
> #0 0x00f6d00b in __kernel_vsyscall ()
> #1 0x009fdbaa in ____strtoull_l_internal () from /lib/libc.so.6
> #2 0x009ff44a in ____strtof_l_internal () from /lib/libc.so.6
> #3 0x00a3bbb5 in _IO_default_pbackfail_internal () from /lib/libc.so.6
> #4 0x00a46671 in memalign () from /lib/libc.so.6
> #5 0x00a4235f in _obstack_newchunk () from /lib/libc.so.6
> #6 0x00a4334e in strverscmp () from /lib/libc.so.6
> #7 0x083d54cd in operator new (size=1160) at /home/build/exp.cpp:8145
> #8 .............
What are the possible reasons I can end up with this? The memory usage of my machine is quite low, about 8% of 12GB, I don't think memory is an issue ( the core dump is about 700MB ).
The new operator is overloaded to use malloc:
void * operator new (size_t size) throw()
{
return malloc(size);
}
You most likely overrun an new'd/malloc'ed block earlier, destroying the book-keeping data malloc uses, hence it crashes the next time you try to malloc something.
You should compile with all warnings and debug info (e.g. g++ -Wall -g) then use valgrind.
Your implementation of new is wrong. malloc can fail, and in that case your new should throw an exception. It is not allowed to return NULL
If your GCC is recent, consider also using -fsanitize=address

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?