【问题标题】:How do I get gdb to tell me memory characteristics a given address如何让 gdb 告诉我给定地址的内存特性
【发布时间】:2016-12-13 20:51:52
【问题描述】:

我有一个核心的 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 会话中确定吗?

【问题讨论】:

  • C++ 遵循只为您需要的东西付费的理念,因此它不会浪费时间测试和阻止明显的错误。
  • 那篇文章没有回答我的问题。我不是在问读取释放的内存地址是否会崩溃——在很多情况下显然不会。我什至在我的帖子中承认这一点。我在问 gdb 可以告诉我关于死后核心中的内存地址的什么信息。

标签: c++ memory gdb


【解决方案1】:

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 的内部工作原理,能够追逐它们的内部数据结构,并且能够手动规划它们的竞技场。这不是一项微不足道的任务。使用带有保留调试符号的标准库版本会有所帮助。

如果做不到这一点,您可以尝试映射程序的内存,包括静态/全局变量、堆栈变量、上面指向的所有已分配数据结构,以及其他已分配数据结构中的指针指向的所有已分配数据结构。我知道没有工具能够从事后转储中自动执行此操作,尽管理论上此类工具是可能的。

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

【讨论】:

  • info proc 仅适用于实时调试,不适用于事后分析 (core)。
  • 谢谢,这很有帮助。
猜你喜欢
  • 2011-03-01
  • 1970-01-01
  • 2020-10-23
  • 2018-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
相关资源
最近更新 更多