如何查找给定地址是堆还是堆栈

时间:2015-11-19 08:02:58

标签: c linux unix gcc

我需要查找给定地址是堆还是堆栈。在Linux中有可靠的方法吗?

我已经考虑过以下方法,假设堆栈将向下增长,堆将向堆栈方向增长。这个解决方案有多可靠?我们不使用gcc split-stack

is_stack (void *addr) {
   int a;
   if( &a < addr) return stack;
   else return heap
}

[编辑 - 我看到了一个类似的问题,但这更像是一种理论性质]

2 个答案:

答案 0 :(得分:4)

首先,您的process中可能有多个堆栈,特别是如果它是多线程的(并且某些库可以在没有您要求的情况下启动线程)。而你的流程&#39; virtual address space可能包含的内容多于 heap &amp;

您可以解析/proc/self/maps伪文件。见proc(5)。请注意,由于它是由内核生成的伪文件,因此不涉及物理IO,并且读取&amp;解析/proc/self/maps文件应该非常快。

您的流程的地址地图可以通过调用mmap(2)munmapexecvemprotect和其他一些系统调用来更改(请参阅syscalls(2)  得到他们的清单);使用strace(1)来了解完成了哪些系统调用。对malloc的任何调用(由许多函数内部调用,包括fopen ...)或free(以及dlopen等等......)可以(但不会总是)使用它们,因此缓存解析/proc/self/maps的结果不是一个可靠的选择。

首先尝试终端中的cat /proc/$$/maps命令(显示shell的虚拟地址空间的描述)。

正如许多人评论的那样,由于ASLR,即使只有一个堆栈,你也不知道堆栈和堆的相对位置。一个可能的诀窍可能是启动你的main,其中包含一些局部变量的地址(甚至是main的{​​{1}}第一个参数或{{1} }}在某些全局argc中,稍后比较你的地址,即测试argv[0]。请注意Boehm's garbage collector正在做类似的事情。

但最可靠的方法是阅读和解析void*stackbottom;,这应该是相当快的,当然是一个程序化的解决方案(内核动态提供有关其状态和过程的信息状态通过if( &a < addr && &a > stackbottom)并且没有物理 IO参与阅读它。)

然而,在堆栈上或在堆中是一个定义不明确的属性(换句话说,堆栈是一个比复杂更复杂的概念你想象的那样)。你需要更准确地了解你真正想做的事情。

另外,重新定义自己的/proc/self/maps/proc/等,并让malloc管理一些记忆地图。

答案 1 :(得分:2)

C标准没有堆栈的概念,因此语言本身无法告诉您。

但你确实提到了Linux,所以一切都没有丢失 - 你可以通过相当多的工作来实现这一点。

如果将定义为malloc分配的内存,可以考虑构建自己的内存分配系统。许多C编译器允许您在链接到程序的所有库的链接时为其注入不同的malloc,因此这种方法非常可行。 (见LD_PRELOAD)。当然,替换malloc的主要内容只会调用标准函数。但另一部分将维护一个已分配内存的表。您可以在需要编写的测试函数中使用该信息。

您需要对callocfree和&amp; c执行相同操作。

相关问题