我们有一种监控负载和机制的机制。存储捕获所引用地址的指令。我想对地址进行分类,无论它们属于堆栈,堆还是分配静态变量的区域。有没有办法以编程方式进行这种分类?
我最初的想法是在进程开始运行时立即执行一个带有小内存请求(1?)的malloc(),这样我就可以捕获"基地址"堆的(或起始地址)。这样,我可以区分静态分配的那些变量和其余的变量。对于那些不属于静态区域的引用(那些是堆和堆栈),我怎么能区分它们呢?
一些小测试显示以下简单代码(在Linux 3.18 / x86-64中使用gcc 4.8.4编译)
#include <stdio.h>
#include <stdlib.h>
int x;
int foo (void)
{
int s;
int *h = malloc (sizeof(int));
printf ("x = %p, *s = %p, h = %p\n", &x, &s, h);
}
int main (int argc, char *argv[])
{
foo();
return 0;
}
显示了地址空间的一些随机化(不是在静态变量中,而是在剩下的部分 - 堆和堆栈中),这可能会增加一些不确定性,但可能是一种找到地址空间的这些区域的限制的方法。 / p>
答案 0 :(得分:8)
没有标准的C API,这意味着所有可能的解决方案都将基于特定于平台的黑客攻击。此外,这个答案仅限于单线程应用程序。
堆栈是一个连续的内存区域。因此,您需要知道的只有两个数字:堆栈的顶部和堆栈的底部。堆栈的顶部基本上受当前函数的堆栈帧的限制。但是,由于无法从C代码访问当前堆栈帧的大小,因此很难确定当前帧的确切位置。这里的技巧是从当前调用另一个函数,并使用被调用函数堆栈帧中的地址作为stack_top
的边界值。
学习堆栈的底部更简单 - 它的值在程序执行期间保持不变,并且受入口点函数的堆栈帧(C程序中的main()
)的限制。因此,在main()
函数中获取某个局部变量的地址就足够了。
另一个警告是x86
堆栈向后增长,这意味着堆栈顶部的地址小于底部。这段代码总结了一下:
void *stack_bottom;
bool IS_IN_STACK(void *x) __attribute__((noinline));
bool IS_IN_STACK(void *x) {
void *stack_top = &stack_top;
return x <= stack_bottom && x >= stack_top;
}
int main (int argc, char *argv[]) {
int x;
stack_bottom = &x;
...
逻辑在这里更简单。静态变量在固定的,特定于平台的地址开始的内存区域中分配。通常该区域位于存储器中的所有其他区域之前。因此,唯一需要学习的是此静态存储区的 end 地址。
幸运的是,GCC链接器provides symbols end
,edata
和etext
表示.bss
,.data
和{{1}的结尾分别是段。静态变量在.text
或.bss
段中分配,因此在大多数平台上进行此检查应该足够了:
.data
此宏检查#define IS_STATIC(x) ((void*)(x) <= (void*)&end || (void*)(x) <= (void*)&edata)
和edata
,以避免假设end
和.bss
中的哪一个位于内存中。
堆变量通常直接分配在.data
和.data
区域中的地址之后的地址中。但是,有时堆地址可能属于非连续的内存范围。因此,您可以在此处执行的最佳操作是读取Linux进程文件以查找其他答案中建议的内存映射。或者,只需检查.bss
和IS_IN_STACK
是否都返回false。
使用这些宏的完整程序:
IS_STATIC
答案 1 :(得分:2)
我想为了获得正确的结果,您应该在Linux上解析/proc/<pid>/maps
文件。样本内容:
# cat maps
00400000-00407000 r-xp 00000000 fc:02 1837717 /sbin/getty
00606000-00607000 r--p 00006000 fc:02 1837717 /sbin/getty
00607000-00608000 rw-p 00007000 fc:02 1837717 /sbin/getty
00608000-0060a000 rw-p 00000000 00:00 0
0252e000-0254f000 rw-p 00000000 00:00 0 [heap]
7f3ca601f000-7f3ca6833000 r--p 00000000 fc:02 2105304 /usr/lib/locale/locale-archive
...
7f3ca7656000-7f3ca7657000 r--p 00022000 fc:02 1711858 /lib/x86_64-linux-gnu/ld-2.19.so
7f3ca7657000-7f3ca7658000 rw-p 00023000 fc:02 1711858 /lib/x86_64-linux-gnu/ld-2.19.so
7f3ca7658000-7f3ca7659000 rw-p 00000000 00:00 0
7fffbbcf2000-7fffbbd13000 rw-p 00000000 00:00 0 [stack]
7fffbbdfc000-7fffbbdfe000 r-xp 00000000 00:00 0 [vdso]
7fffbbdfe000-7fffbbe00000 r--p 00000000 00:00 0 [vvar]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
请参阅proc(5)
。