2016-12-13 28 views
0

我有一个核心gdb会话,它表明在读取其中一个成员时,在指针的解引用中存在段错误。该指针的值非空。我认为这意味着该进程无法访问内存地址。如何从核心的postmortem gdb会话中获取此信息?我该如何让gdb告诉我一个给定地址的内存特征

例如,假设下面的程序:

#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; 
} 

如果我调试这个程序用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) 

我可以从PTR得到什么样的内存信息?我可以确定ptr指向释放内存吗?由于在我正在调试的核心(不在上面的玩具测试二进制文件中),我得到了一个段错误解引用 - 即从一个指针读取,而不是写入一个指针,我想原始内存位置被分页出去,因此不是过程可访问的内存?我可以从gdb会话中确定吗?

+0

可能重复的[C + +删除 - 它删除我的对象,但我仍然可以访问数据?](http://stackoverflow.com/questions/1930459/c-delete-it-deletes-my-objects-but-我仍然可以访问数据) – user4581301

+0

C++遵循一种只为你所需要的付款的理念,所以它不会浪费时间来测试和阻止公然错误的。 – user4581301

+0

该帖子没有回答我的问题。我并没有问是否读取释放的内存地址会崩溃 - 在很多情况下显然不会。我甚至在我的帖子中承认。我问的是gdb可以告诉我关于postmortem核心内存地址的内容。 – firebush

回答

2

gdb没有动态分配的概念,也没有关于释放内存的想法。它可以告诉的地址是否被映射到进程的地址空间或不:

gdb> info files 
gdb> maintenance info sections 

但因为你的程序有SIGSEGV崩溃,你已经知道它曾试图访问映射的地址。

其他工具可以检测对已释放内存的访问。 valgrind通常是你的朋友,但不适用于验尸调试。您需要运行valgrind下的程序以了解其行为。

段引用很少意味着指针指向已释放的内存。通常情况下,指针本身驻留在被释放的内存中,并被重用和覆盖。因此,

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 

从非检测可执行文件的事后转储中提取这类信息非常困难。您需要熟悉mallocnew的内部工作,能够追踪其内部数据结构,并手动绘制出他们的竞技场。这不是一项简单的任务。使用具有保存调试符号的标准库版本将有所帮助。如果做不到这一点,你可以尝试并映射出你程序的内存,包括静态/全局变量,堆栈变量,上面指向的所有分配的数据结构,以及其他分配的数据结构中指针指向的所有分配的数据结构。我知道没有哪种工具能够从验尸转储中自动执行此操作,但理论上这些工具是可能的。

映射完程序存储器或映射了程序存储器的某些部分后,可以试着找出不同类型的不相关对象是否位于无效指针所在的地址。如果是这样,你可能会得出这样的结论:两个对象中的一个可能被释放,释放后非法访问的内存。

+0

'info proc'仅适用于实时调试,不适用于验后('core')。 –

+0

@EmployedRussian Oops你是对的,编辑。 –

+0

谢谢,这非常有帮助。 – firebush

相关问题