Search code examples
c++gdbassertcoredump

Debugging an assertion with gdb shows weird std::string size


I have a problem with an assertion in a C++ program.

HA_Archive & HA_Archive::operator << (const string & str) {
    buffer[wcursor] = HA_TYPE_STRING;
    wcursor++;
    unsigned size = str.size();
    CASSERT((bufferSize > wcursor + size),"buffer exceeds the maximum");

CASSERT is a simple assert, and there is the problem.

The program left a core dump that I have debugged with gdb, and I found something strange.

Program terminated with signal 6, Aborted.
#0  0xb7766424 in __kernel_vsyscall ()
(gdb) bt
#0  0xb7766424 in __kernel_vsyscall ()
#1  0xb6cd1cb1 in raise () from /lib/libc.so.6
#2  0xb6cd33e8 in abort () from /lib/libc.so.6
#3  0xb6ccb58c in __assert_fail () from /lib/libc.so.6
#4  0x086c6dbd in HA_Archive::operator<< (this=0xb2610fb8, str=@0xb49e1f08) at HA_Archive.cxx:94
#5  0x0849b4d3 in PortDriver::serialize (this=0xb49e1ed8, ar=@0xb2610fb8) at PortDriver.cxx:624
#6  0x0838ed80 in PortSession::serialize (this=0xb49e1630, ar=@0xb2610fb8) at PortSession/PortSession.h:71

(gdb) frame 4
#4  0x086c6dbd in HA_Archive::operator<< (this=0xb2610fb8, str=@0xb49e1f08) at HA_Archive.cxx:94
94  HA_Archive.cxx: No such file or directory.
    in HA_Archive.cxx
(gdb) print str
$1 = (const string &) @0xb49e1f08: {static npos = 4294967295, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0xb322f9b4 "NOT-SET"}}
(gdb) print wcursor
$2 = 180
(gdb) print bufferSize
$3 = 4096
(gdb) print size
$4 = 171791040

Printing the str I can see that it has "NOT-SET" and that is OK, but when I print the variable size that is str.size() the value is huge! Obviously is the cause that make the asserts fails, because bufferSize is 4096 and wcursor is only 180.

I am very far to be and expert in gdb so my first question is if I am doing something wrong whit it. Maybe size is not the real value at runtime?

My second question is: If gdb is showing the correct value of size, why I am seeing correctly the string "NOT-SET" when I print it, but the size is that huge number?


Solution

  • There are a few ways this can happen.

    The string could really be that size, but the contents could have a nul character at str[7], which would cause GDB to stop printing it out.

    Or maybe something has scribbled on your heap and has overwritten the memory location that stores the string's size, so although the contents are still only 7 bytes long the size member has been overwritten with garbage.

    Or str could just be a dangling reference and the memory pointed to by _M_p still contains the string "NOT-SET" but the memory containing the size member has been re-used for something else.

    I would try running under valgrind to ensure there are no buffer overruns that might be overwriting the member, or use-after-free errors.