2

I have a gdb session for a core and it indicates that there's a segfault in a dereference of a pointer when reading one of its members. The pointer is non-null in value. I assume this means that the memory address was not accessible to the process. How do I get this information from a postmortem gdb session of the core?

For instance, given the following program:

#include <iostream>

using namespace std;

int
main(int argc, char* argv[])
{
    int *ptr = new int(5);
    cout << "I can access it here: " << *ptr << endl;

    delete ptr;

    cout << "But I shouldn't do so here: " << *ptr << endl;
    return 0;
}

If I debug this program with gdb:

$ g++ -g -Wall test.cc -o test
$ gdb ./test
(gdb) b 13
...
Breakpoint 1 at 0x400943: file test.cc, line 13.
(gdb) run
Starting program: /usr/home/nfs/bneradt/test/test
I can access it here: 5

Breakpoint 1, main (argc=1, argv=0x7fffffffe348) at test.cc:13
13          cout << "But I shouldn't do so here: " << *ptr << endl;
(gdb)

What kind of memory information can I get from ptr? Can I determine that ptr points to freed memory? Since in the core I'm debugging (not in the toy test binary above) I got a seg fault dereferencing - i.e., reading from, not writing to - a pointer, I suppose the original memory location got paged out and therefore wasn't process-accessible memory? Can I determine that from the gdb session?

firebush
  • 5,180
  • 4
  • 34
  • 45
  • Possible duplicate of [C++ delete - It deletes my objects but I can still access the data?](http://stackoverflow.com/questions/1930459/c-delete-it-deletes-my-objects-but-i-can-still-access-the-data) – user4581301 Dec 13 '16 at 21:17
  • C++ follows a philosophy of only pay for what you need, so it doesn't bother wasting time testing for and blocking the blatantly wrong. – user4581301 Dec 13 '16 at 21:18
  • That post doesn't answer my question. I'm not asking about whether reading a freed memory address will crash - it obviously wouldn't in many circumstances. I even acknowledge that in my post. I'm asking about what gdb can tell me about a memory address in a postmortem core. – firebush Dec 13 '16 at 21:47

1 Answers1

3

gdb has no concept of dynamic allocation and no idea about freed memory. It can tell whether an address is mapped into the process address space or not:

gdb> info files
gdb> maintenance info sections

but since your program has crashed with a SIGSEGV, you already know it has tried to access an unmapped address.

Other tools can detect access to freed memory. valgrind is normally your friend, but not for post-mortem debugging. You need to run the program under valgrind to gain insight to its behaviour.

A segfault while dereferencing a pointer seldom means that the pointer is pointing to a freed memory. More often than not, it is the pointer itself that resides in freed memory that got reused and overwritten. So

int** ptrarr = new int*[5];
ptrarr[3] = new int(5);
// later
delete [] ptrarr;
// later still after many memory allocations
int* ptr = ptrarr[3]; // ptrarr points to freed memory; UB but no segfault
                      // ptr contains a seemingly random value
int num = *ptr;       // possible segfault

It is very hard to extract this kind of information from a post-mortem dump of a non-instrumented executable. You need to be familiar with the internal working of malloc and new, be able to chase their internal data structures, and map out their arena by hand. This is not a trivial task. Using a version of the standard library with preserved debugging symbols will help.

Failing that, you may try and map out your program's memory, including static/global variables, stack variables, all allocated data structures pointed to by the above, and all allocated data structures pointed to by pointers in other allocated data structures. I know about no tools that are able to do this automatically from a post-mortem dump, though in theory such tools are possible.

Having mapped the program memory, or perhaps some part of it, you can try and find out if an unrelated object of a different type sits at the address where your invalid pointer resides. If so, you may conclude that one of the two objects might be freed memory that was illegally accessed after being freed.

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243