【问题标题】:Identifying if an address belongs to heap or stack or registers识别地址是否属于堆或堆栈或寄存器
【发布时间】:2012-08-03 09:16:37
【问题描述】:

我有一个指向 C/C++ 变量的指针。是否可以准确地确定该变量属于哪个内存段?如果是,如何?

注意:我只有这个变量的地址,如果变量是本地/全局等,则没有更多信息。

【问题讨论】:

  • 不可能,至少不能以便携的方式。
  • 您要解决什么问题?您需要运行时或编译时解决方案吗?寄存器没有地址。
  • 我们刚刚争论了全局变量是属于栈还是堆,想确认一下:P
  • @Amit - 回答真正的问题:全局变量是独立的,不是堆栈也不是堆。
  • @BradTilley:未指定静态存储是否使用堆,以及如果您依赖它,则为未定义行为。静态存储不能使用堆栈,因为后者强加了与前者不兼容的破坏顺序语义。然而,堆并没有施加这样的限制,因此可以作为静态存储和堆栈的基础。

标签: c++ c memory-management heap-memory stack-memory


【解决方案1】:

了解您的架构是否有指向堆或堆栈区域的指针。通常有一些堆栈指针或帧指针..

然后将您的实际地址与这些地址进行比较,并确定它们属于哪里。

【讨论】:

  • 呵呵,是的,你是对的 ;) 但是如果你谈论异国架构,也可以将全局变量放在堆栈或堆中。这也取决于架构。
  • 我有没有提到 Univac 硬件也没有堆栈? .-)
  • 我只相信1981年以后发明的东西呵呵 :D
  • @BoPersson:只有当成堆的打孔卡不算在内时:P
【解决方案2】:

如果您使用的是 linux(不确定其他 unice),您可能可以在文件 /proc/<pid>/maps 中找到信息

【讨论】:

    【解决方案3】:

    您可以首先确定可执行文件中不同部分的开头和结尾。为此,您最终需要在链接描述文件中围绕每个部分添加一些变量,如下所示:

    SECTIONS {
        [...]
        .data : {
            data_start = .;
            *(.data)
            data_end = .;
        }
        [...]
    }
    

    然后您可以在您的 C/C++ 代码中将这些变量声明为外部变量,并直接使用它们来比较您要识别的地址。

    调整链接描述文件可能并不容易。使用 gcc,您可以将其转储:

    gcc -Wl,-verbose whatever.c
    

    然后尝试查找已经在(混乱的)输出中定义的变量。

    要获得堆栈的边界,您可以在 main() 函数的开头实例化一个虚拟变量,并将其地址保存为堆栈的顶部,然后在当前位置实例化另一个,这将给出你最底层。但是请注意,编译器的行为可能与此完全不同(不能保证 C 中变量的堆栈顺序,甚至不能保证堆栈的使用),因此这应该可以工作,但不可移植。

    最后,对于堆,我没有诀窍。我只是推断不在 data/bss/derivated 中且不在堆栈中的变量将在堆中(不包括寄存器,但如果你能获得地址,我敢打赌编译器永远不会使用仅寄存器存储)。

    【讨论】:

      【解决方案4】:

      我不知道它是否适合您的情况,但您可以尝试objdump -t 查看 elf 文件的符号表。您所需要的只是变量的地址。在那里您可以找到向您显示每个变量的部分的标志。有关详细信息,请参阅 objdump 的手册页。

      示例输出:

      0804a020 g     O .bss   00000004              var
      

      它说varglobal Object 在地址0804a020,部分.bss

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-10-11
        • 2021-01-25
        • 2020-04-12
        • 2011-06-29
        • 1970-01-01
        • 2023-03-20
        • 2016-06-26
        相关资源
        最近更新 更多