0
votes

I'm using std::stringstream to format a representation of a tree for a program I am writing. I am encountering a strange crash that only appears sporadically:

free(): invalid pointer
make: *** [makefile:29: run] Aborted (core dumped)

When I checked the backtrace with gdb, I found the following:

(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007ffff7be4859 in __GI_abort () at abort.c:79
#2  0x00007ffff7c4f3ee in __libc_message (action=action@entry=do_abort, fmt=fmt@entry=0x7ffff7d79285 "%s\n") at ../sysdeps/posix/libc_fatal.c:155
#3  0x00007ffff7c5747c in malloc_printerr (str=str@entry=0x7ffff7d774ae "free(): invalid pointer") at malloc.c:5347
#4  0x00007ffff7c58cac in _int_free (av=<optimized out>, p=<optimized out>, have_lock=0) at malloc.c:4173
#5  0x00007ffff7f043da in std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::~basic_stringstream() () from /lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x0000555555557335 in Node<unsigned int, TestRecord, 3u, 3u>::repr_tree[abi:cxx11](unsigned int) (this=0x55555556f670, depth=3) at BPlusTree.h:306
#7  0x00005555555572a8 in Node<unsigned int, TestRecord, 3u, 3u>::repr_tree[abi:cxx11](unsigned int) (this=0x55555556f860, depth=2) at BPlusTree.h:330
#8  0x00005555555572a8 in Node<unsigned int, TestRecord, 3u, 3u>::repr_tree[abi:cxx11](unsigned int) (this=0x55555556f9c0, depth=1) at BPlusTree.h:330
#9  0x00005555555572a8 in Node<unsigned int, TestRecord, 3u, 3u>::repr_tree[abi:cxx11](unsigned int) (this=0x55555556f910, depth=0) at BPlusTree.h:330
#10 0x0000555555556c72 in BPlusTree<unsigned int, TestRecord, 3u, 3u>::repr_tree[abi:cxx11]() (this=0x7fffffffdfe0) at BPlusTree.h:713
#11 0x00005555555564eb in test_tree_insert (n=20) at CS4412PjXCharlesJohnson.cpp:68
#12 0x00005555555568c9 in main (argc=1, argv=0x7fffffffe148) at CS4412PjXCharlesJohnson.cpp:124

The relevant functions being called are the following:

std::string repr_tree(unsigned depth)
  {
    std::stringstream stream;
    std::string       spacing(2 * depth, ' ');
    if (isLeaf)
    {
      stream << spacing << "|-+" << std::endl;
      for (unsigned i = 0; i < numVals; i++)
      {
        if (vals[i] == nullptr)
        {
          break;
        }
        stream << spacing << "  |- " << vals[i]->to_string() << std::endl;
      }
    }
    else
    {
      stream << spacing << "--+";
      for (unsigned i = 0; i < numKeys; i++)
      {
        stream << " " << keys[i];
      }
      stream << std::endl;
      for (unsigned i = 0; i < numChildren; i++)
      {
        stream << children[i]->repr_tree(depth + 1);
      }
      stream << std::endl;
    }
    return stream.str();
  }

And:

std::string to_string() override
  {
    std::stringstream stream;
    stream << "TestRecord<" << get_key() << ">";
    return stream.str();
  }

In doing some searching online, the only thing I found that can cause std::stringstream to trigger this error is when an EOF is written to it followed by other subsequent writes, but I cannot find anything in my code that would cause such a thing. I'm also not doing any fancy memory management that would corrupt the dynamic memory structs used by malloc and free, so I'm at a bit of a loss. Is there something I'm missing or a way for me to better debug this issue?

We'll need a minimal reproducible example. You can also try using an address sanitizer.HolyBlackCat
You could also try to step through the code with a debugger. There are video tutorials if you don't know how to. As a new user here, please take the tour and read How to Ask.Ulrich Eckhardt
@HolyBlackCat I'll give it a tryuser852541