如何查找变量是在堆栈还是堆中分配?

偶然发现这个面试问题,

在C中,给定变量x ,如何确定该变量的空间是在堆栈还是堆上分配?

(有没有办法以编程方式找到它而不必通过符号表等?并且确定是否在堆栈或堆中分配空间有任何实际意义吗?)

不,不是一般的。

你知道gcc -fsplit-stack吗?

由实现决定是分配连续堆栈还是堆栈,其中块与内存中的堆块交错。 祝你好运,确定在分割后是否为堆或堆栈分配了块。

注意:无论如何,这是一个无用的信息……

如果您正在构建将堆栈存储在比堆大的地址上的体系结构,则可以将变量地址与堆栈的底部进行比较。 使用pthread线程API,此比较将如下所示:

 #include  #include  #include  #include  int is_stack(void *ptr) { pthread_t self = pthread_self(); pthread_attr_t attr; void *stack; size_t stacksize; pthread_getattr_np(self, &attr); pthread_attr_getstack(&attr, &stack, &stacksize); return ((uintptr_t) ptr >= (uintptr_t) stack && (uintptr_t) ptr < (uintptr_t) stack + stacksize); } 

考试:

 int main() { int x; int *p1 = malloc(sizeof(int)); int *p2 = &x; printf("%d %d\n", is_stack(p1), is_stack(p2)); return 0; } 

...按预期打印0 1

上面的代码不会检测其他线程中的堆栈存储。 为此,代码需要跟踪所有创建的线程。

任何标准BUT都不保证这一点

在大多数平台上,堆栈从可用的最高地址开始增长,如果地址的最高有效字节位于平台的可用内存空间的上半部分,则堆从底部开始增长,并且您还没有分配千兆字节的内存,这是一个非常好的赌注它在堆栈上。

 #include  #include  int main() { int x = 0; int* y = new int; unsigned int a1 = (int) &x; unsigned int a2 = (int) y; std::cout< 

在我输入的机器上给出输出ffbff474 21600

这可能是一个棘手的问题。 变量具有自动或静态存储持续时间[*]。 您可以相当安全地说自动化是“在堆栈上”分配的,至少假设它们没有优化到寄存器中。 标准的要求不是“堆栈”,但符合要求的C实现必须维护调用堆栈并将自动变量与调用堆栈的级别相关联。 因此无论它实际上做什么的细节,你几乎可以称之为“堆栈”。

具有静态存储持续时间的变量通常存在于一个或多个数据部分中。 从OS的POV,可以在程序启动之前从堆中分配数据部分,但是从程序的POV它们与“免费存储”无关。

您可以通过检查变量在源中的定义来判断变量的存储持续时间 – 如果它在函数范围内,那么除非标记为static否则它是自动的。 如果它不在函数范围内,则它具有静态持续时间,无论它是否标记为static (因为static关键字表示不同的东西)。

没有可移植的方法来告知变量的存储持续时间,但是特定的实现可能提供了执行此操作的方法,或者可以使用具有更高或更低可靠性的工具来进行猜测。

对象也可以具有动态存储持续时间(通常是“在堆上分配”的意思),但是这样的对象不是变量 ,所以如果有的话,这将是技巧。

[*]或C11和C ++ 11中的线程局部。

我不认为它有解决方案。 代码可以通过堆栈(堆)地址范围调整var的地址,但这不是一个确切的方法。 最多,代码只能在某些特定平台上运行。

不,不可能通过内存位置确定编译器必须支持isstack()才能移植。