How to find if a variable is allocated in stack or heap?
Asked Answered
A

7

23

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?

(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?)

Allseed answered 5/12, 2012 at 9:5 Comment(7)
see the assembly code.. you can get it thereGigantes
Did he mention anything else? Like architecture, compiler, OS? Else i'd say no.Gluck
No, this was the only information given.Allseed
I don't think there's a portable solution. There's no such thing as a stack or a heap in either language, so the question is much more about a given implementation of the language. If you're looking at GCC, for example, it has a ton of malloc-related utilities that might help.Chancellor
Oh, are you allowed to specify the type of x?Chancellor
They're not usually after a "correct answer" - they're usually after a demonstration of knowledge of heap, stack, calling conventions, where local variables live and then on to things like compiler optimisation, the direction stack grows, how different architectures manage heap and stack etc. It's a fairly open ended question that can give an interviewer a good idea of what someone knows.Teodoro
@Joe: still, I don't like being tricked...Benignity
B
14

No, not in general.

Do you know of 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.

Benignity answered 5/12, 2012 at 9:43 Comment(7)
I suppose that with -fsplit-stack you could reasonably answer "both" for an automatic variable. It's on the stack, and the stack is on the heap.Grovergroves
@SteveJessop: Ah! That should get the interviewer thinking :)Benignity
not useless at all. I have a function destroy_something(something**s). It would be very helpful to know if *s is on the heap or stack in order to know if to call free on *s or not.Quanta
@GerardoZinno: The simpler solution here is to separate destruction and deallocation; if the variable is on the stack, deallocation is automatic, otherwise the owner must deallocate it.Benignity
@MatthieuM Yes. I was just saying it would not be a totally useless feature to have as your post was saying before the editing :)Quanta
@GerardoZinno: Well, I still think, personally, that it is useless -- though as it is subjective, I preferred to scrub it from my answer. By useless I don't mean it cannot be used, but that all uses I can think of -- included the one you presented -- seem dubious to me: brittle, "clever", etc...Benignity
@MatthieuM. I agree with you.Quanta
J
10

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:

#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.

The above code will not detect storage from stacks in other threads. To do that, the code would need to track all created threads.

Josefinejoseito answered 5/12, 2012 at 9:17 Comment(0)
E
3

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.

Eidson answered 22/2, 2013 at 12:30 Comment(1)
Note: Prolly won't work at all for multi-threaded applications.Contribution
G
2

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. 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".

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. 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).

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.

Grovergroves answered 5/12, 2012 at 9:59 Comment(0)
G
1

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. At most, the code can only run in some certain platforms.

Guberniya answered 5/12, 2012 at 9:13 Comment(0)
B
0

No it's not possible to determine that by memory location, the compiler would have to support it with isstack() to be portable.

Buchmanism answered 3/1, 2013 at 20:58 Comment(0)
A
0

One possible way to track memory allocation SPECIFICALY ON THE HEAP in C++ is overloading the new operator to keep tracking that for you. Then you know that if the memory is not allocated on the heap, it must be allocated on the stack.

#include <iostream>
#include <string>

// Variable to track how many allocations has been done.
static uint32_t s_alloc_count = 0;

void* operator new(size_t size){
    s_alloc_count++;
    std::cout << "Allocating " << size << " bytes\n";
    return malloc(size);
}

Tracking the variable s_alloc_count you should be capable of see how many allocations on the heap has been done and have the size of these allocations printed on the console. Using debug tools like breakpoints, running the code "step-by-step" and console logging is one way to track where are these allocations. This is not an automated way but is a way to do that.

OBS: This tip should be only used for tests, avoid this type of code in production code.

Ancestor answered 8/11, 2022 at 11:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.