我有一个要求,find一个给定的地址是在堆或堆栈。 有没有一种可靠的方法来在Linux中做到这一点?
我曾经想过下面的方法,假设堆栈会向下增长,堆堆栈会长大。 这个解决scheme有多可靠? 我们不使用gcc split-stack
。
is_stack (void *addr) { int a; if( &a < addr) return stack; else return heap }
[编辑 – 我看到了一个类似的问题,但更多的是理论]
首先,你可能在你的进程中有多个堆栈,特别是如果它是多线程的(有些库可以在你没有请求的情况下启动线程)。 而且你的进程的虚拟地址空间可能比堆和堆栈更多 。
您可能会解析/proc/self/maps
伪文件。 参见proc(5) 。 请注意,由于它是由内核生成的伪文件,因此不涉及物理IO,读取和解析/proc/self/maps
文件应该非常快。
你的进程的地址映射可以通过调用mmap(2) , munmap
, execve
, mprotect
和一些其他的系统调用来改变(参见syscalls(2)以得到它们的列表)。 使用strace(1)来了解哪些系统调用已经完成。 任何对malloc
调用(内部被许多函数调用,包括fopen
…)或者free
(以及对dlopen
等等等) 都可能 (但不会总是)使用它们,所以缓存解析/proc/self/maps
的结果/proc/self/maps
不是一个可靠的选项。
首先尝试在终端中显示cat /proc/$$/maps
命令(显示你的shell的虚拟地址空间的描述)。
正如很多人所评论的,由于ASLR ,即使只有一个堆栈,您也不知道堆栈和堆的相对位置。 一个可能的技巧可能是在某些全局void*stackbottom;
放入一些局部变量的地址(甚至是main
的argc
第一个参数或者argv[0]
)的地址来启动main
void*stackbottom;
,稍后再比较一下你的地址,那就是测试if( &a < addr && &a > stackbottom)
。 注意到Boehm的垃圾回收器正在做类似的事情。
但最可靠的方法是读取和解析/proc/self/maps
,这应该是相当快的,当然是一个程序化的解决方案(内核动态地提供有关其状态和过程状态的信息通过/proc/
和没有物理 IO涉及阅读)。
而且,堆栈或堆中的指针是一个不明确的属性(换句话说, 堆栈或堆是一个比你想象的复杂得多的概念)。 你需要更精确地知道你真正想做什么。
另外,重新定义你自己的malloc
, free
等,并让你的malloc
管理一些内存映射。
C标准没有堆或栈的概念,所以语言本身不能告诉你。
但是你提到了Linux,所有的都不会丢失 – 你可以用一点点工作来实现。
如果将堆定义为由malloc
分配的malloc
,则可以考虑构建自己的内存分配系统。 许多C编译器允许您在链接到您的程序的所有库中链接一个不同的malloc
,因此这种方法是非常可行的。 (请参见LD_PRELOAD)。 当然,您的替换malloc
的主要内容将简单地调用标准函数。 但另一部分将维护一个分配内存的表。 您可以在测试函数中使用您需要编写的信息。
你需要为calloc
, free
和&c做同样的事情。