barak manos
barak manos

Reputation: 30136

A method for computing stack-size

I assume that this question is more related to compilation/linkage rather than to the C standard.

Consider the following method for computing stack-size:

#define ORDER(a,b,c) ((a) <= (b) && (b) <= (c))

int global;

int main()
{
    int local;

    unsigned long long dataAddr  = (unsigned long long)&global;
    unsigned long long stackAddr = (unsigned long long)&local;
    unsigned long long codeAddr  = (unsigned long long)main;

    if (ORDER(stackAddr,dataAddr,codeAddr) || ORDER(codeAddr,stackAddr,dataAddr))
        printf("Stack size is %llu bytes\n",dataAddr-stackAddr);

    else if (ORDER(stackAddr,codeAddr,dataAddr) || ORDER(dataAddr,stackAddr,codeAddr))
        printf("Stack size is %llu bytes\n",codeAddr-stackAddr);

    else
        printf("Stack size cannot be computed with this method\n");

    return 0;
}

Except for the obvious case in which the stack is located after the code-section and the data-section, what other possible cavities exist in this method?

Is it possible that one or more sections do not start where I'm expecting them to?

Thanks

Upvotes: 0

Views: 79

Answers (2)

user395760
user395760

Reputation:

I don't see how this even begins to be a sensible approach. Among other things, it assumes

  • The stack and globals/code are right next to each other with nothing else in between
  • The stack starts at the "correct" end of the region allocated to it, respectively grows in the correct direction
  • When using codeAddr, it assumes &main points at the start/end of the "code" segment; even if you only define main, a lot of other code is linked in by default.
  • When using dataAddr, it assumes &global points at the start/end of the "data" segment; even if you only define this variable, your standard library will define some variables too.

There is no good reason to assume any of these things. Furthermore, it's completely unnecessary. There are reliable mechanisms for finding out the stack size, although they are OS-specific, they are at least portable among different architectures running that OS, and they don't suffer from the many minor inaccuracies your method will have if all assumptions are met (for example, there are usually a couple of unusable pages at the "end" of stack memory).

Not to mention that there are very few good reasons to care about the stack size to begin with.

Upvotes: 1

Aaron Digulla
Aaron Digulla

Reputation: 328624

In modern computers, there is no good way to determine the maximum stack size anymore. For example, many OSs use the virtual memory system to make the stack start at a random (but high) address. It's random for security reasons. If you have a 64bit system, you have millions or even billions more addresses than actual RAM, so the start of the stack tells you almost nothing. I've even seen systems where the stack grows to larger addresses (HP-UX).

Same goes for the code segment which can be anywhere (and often is today, again security).

Lastly, you have more than one global data segment. In many C implementations, you have at least one initialized and one unintialized global segment. But I've seen compilers which create even more segments for various reasons.

This question contains more nasty details but also some solutions: Checking available stack size in C

Upvotes: 2

Related Questions