简体   繁体   English

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

[英]How to find if a variable is allocated in stack or heap?

Stumbled upon this interview question somewhere,在某处偶然发现了这个面试问题,

In C, Given a variable x , how do you find out if the space for that variable is allocated on the stack or heap?在 C 中,给定一个变量x ,如何确定该变量的空间是在堆栈还是堆上分配的?

(Is there any way to find it out programatically and not having to go through the symbol table, etc? And does finding if the space is allocated in stack or heap has any practical implications?) (有没有办法以编程方式找到它,而不必通过符号表等?查找空间是在堆栈还是堆中分配有任何实际意义吗?)

No, not in general.不,不是一般的。

Do you know of gcc -fsplit-stack ?你知道 gcc -fsplit-stack吗?

It is up to the implementation to decide whether to allocate a contiguous stack or a stack where blocks are interleaved with heap blocks in memory.由实现决定是分配连续堆栈还是分配内存中块与堆块交错的堆栈。 Good luck figuring out whether a block was allocated for the heap or the stack when the latter is split.祝你好运,当后者被拆分时,弄清楚是为堆还是为堆栈分配了块。

If you are working on an architecture that stores the stack on a larger address than the heap, you could compare the variable address with the bottom of the stack.如果您正在研究的架构将堆栈存储在比堆更大的地址上,您可以将变量地址与堆栈底部进行比较。 Using the pthread threading API, this comparison would look like this:使用pthread线程 API,此比较如下所示:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <inttypes.h>

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);
}

The test:考试:

int main()
{
  int x;
  int *p1 = malloc(sizeof(int));
  int *p2 = &x;

  printf("%d %d\n", is_stack(p1), is_stack(p2));
  return 0;
}

...prints 0 1 , as expected. ...按预期打印0 1

The above code will not detect storage from stacks in other threads.上面的代码不会从其他线程的堆栈中检测存储。 To do that, the code would need to track all created threads.为此,代码需要跟踪所有创建的线程。

This is NOT guaranteed by any standard BUT这不受任何标准的保证,但

on most platforms the stack grows down from highest address available, and heap grows up from the bottom if the most significant byte of the address is in the top half of the available memory space for your platform, and you haven't allocated gigabytes of memory, it's a pretty good bet it's on the stack.在大多数平台上,堆栈从可用的最高地址开始向下增长,如果地址的最高有效字节位于平台可用内存空间的上半部分,并且您没有分配千兆字节的内存,则堆从底部向上增长,这是一个很好的赌注,它在堆栈上。

#include <iostream>
#include <stdlib.h>
int main()
{
int x = 0;
int* y = new int;

unsigned int a1 = (int) &x;
unsigned int a2 = (int) y;

std::cout<<std::hex<<a1<<"  "<<a2<<std::endl;
}

gives the output ffbff474 21600 on the machine I'm typing this.在我正在输入的机器上给出输出ffbff474 21600

It might be a trick question.这可能是一个棘手的问题。 Variables have either automatic or static storage duration[*].变量具有自动或静态存储持续时间[*]。 You can fairly safely say that automatics are allocated "on the stack", at least assuming they aren't optimized into registers.您可以相当有把握地说自动程序是“在堆栈上”分配的,至少假设它们没有优化到寄存器中。 It's not a requirement of the standard that there be "a stack", but a conforming C implementation must maintain a call stack and associate automatic variables with the levels of the call stack.标准不要求有“堆栈”,但符合标准的 C 实现必须维护调用堆栈并将自动变量与调用堆栈的级别相关联。 So whatever the details of what it actually does, you can pretty much call that "the stack".所以不管它实际做什么的细节,你几乎可以称之为“堆栈”。

Variables with static storage duration generally inhabit one or more data sections.具有静态存储持续时间的变量通常驻留在一个或多个数据段中。 From the POV of the OS, data sections might be allocated from the heap before the program starts, but from the POV of the program they have no relation to the "free store".从操作系统的 POV 来看,数据部分可能在程序启动之前从堆中分配,但从程序的 POV 来看,它们与“自由存储”无关。

You can tell the storage duration of a variable by examining its definition in the source -- if it's in function scope then it's automatic unless marked static .您可以通过检查源代码中的定义来判断变量的存储持续时间——如果它在函数范围内,那么它是自动的,除非标记为static If it's not in function scope then it has static duration regardless of whether or not it is marked static (since the static keyword means something different there).如果它不在函数范围内,那么无论它是否被标记为static它都具有静态持续时间(因为static关键字在那里意味着不同的东西)。

There is no portable way to tell the storage duration of a variable from its address, but particular implementations might provide ways to do it, or tools that you can use with greater or lesser reliability to take a guess.没有可移植的方法来从地址判断变量的存储持续时间,但特定的实现可能会提供这样做的方法,或者您可以使用或多或少的可靠性来进行猜测的工具。

Objects can also have dynamic storage duration (which generally is what "allocated on the heap" is intended to mean), but such objects are not variables , so that would be the trick if there is one.对象也可以具有动态存储持续时间(这通常是“在堆上分配”的意思),但此类对象不是变量,因此如果存在变量,这将是一个技巧。

[*] Or thread-local in C11 and C++11. [*] 或 C11 和 C++11 中的线程本地。

I don't think it has solutions.我不认为它有解决方案。 The code may adjust var's address by stack(heap) address scope, but it's would not be an exact way.代码可能会通过堆栈(堆)地址范围调整 var 的地址,但这不是一种精确的方法。 At most, the code can only run in some certain platforms.代码最多只能在某些特定平台上运行。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM