我需要查找给定地址是堆还是堆栈。在Linux中有可靠的方法吗?
我已经考虑过以下方法,假设堆栈将向下增长,堆将向堆栈方向增长。这个解决方案有多可靠?我们不使用gcc split-stack
。
is_stack (void *addr) {
int a;
if( &a < addr) return stack;
else return heap
}
[编辑 - 我看到了一个类似的问题,但这更像是一种理论性质]
答案 0 :(得分:4)
首先,您的process中可能有多个堆栈,特别是如果它是多线程的(并且某些库可以在没有您要求的情况下启动线程)。而你的流程&#39; virtual address space可能包含的内容多于 heap &amp; 堆
您可以解析/proc/self/maps
伪文件。见proc(5)。请注意,由于它是由内核生成的伪文件,因此不涉及物理IO,并且读取&amp;解析/proc/self/maps
文件应该非常快。
您的流程的地址地图可以通过调用mmap(2),munmap
,execve
,mprotect
和其他一些系统调用来更改(请参阅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
的主要内容只会调用标准函数。但另一部分将维护一个已分配内存的表。您可以在需要编写的测试函数中使用该信息。
您需要对calloc
,free
和&amp; c执行相同操作。