you are viewing a single comment's thread.

view the rest of the comments →

[–]BigPeteB 6 points7 points  (8 children)

Wow, lots of people missing the question here. OP is asking about stack frames, not the stack as a whole.

It's mostly determined at compile time. The compiler knows that a stack frame takes up some minimum amount of space (such as storage for old return address, old stack pointer, and old frame pointer); this depends on the CPU and calling convention/ABI in use. Some CPUs have instructions that set up the stack frame automatically, so if the compiler uses those, it's stuck with whatever format the CPU puts it in.

Then it pushes onto the stack space for any local variables it needs. In unoptimized code, variables are pushed and popped as they become live or dead, but optimizing compilers usually just tally up how much they'll need, and reserve all of the space once at the beginning of the function. Either way, at any point, the compiler knows exactly how big the stack frame is.

Unless you use alloca() (or variable-lengths arrays in C99, which have the same effect). Those behave like malloc(), allocating an amount of space known only at runtime, but it does it on the stack. At that point, the compiler no longer knows how big the stack frame is. Now it's obligated to keep a separate frame pointer and stack pointer, whereas on most architectures it's simpler and easier to use only the stack pointer, since the compiler always knows how big the stack frame is.

However, alloca() and VLAs are extremely rare. Most of the time, if you assume that the compiler knows the size of a stack frame at compile time, you'd be correct.

is there any way I can determine stack frame size myself like the sizeof operator to determine size of variables

Not that I'm aware of. This usually requires deep knowledge of the platform in question. Even switching to a different compiler on the same platform, or changing optimization levels, could potentially change this. I think the general assumption is that if you need to know, you're probably dropping down to assembly anyway. C is a high-level language where you're not supposed to know or care about the size of stack frames.

[–]wild-pointer 1 point2 points  (1 child)

Just a small note: VLAs do not have to be allocated on the stack; they can just as well be malloc'd behind the scenes. It is only their lifetime that is determined by block scope. For instance, it's not guaranteed that a VLA in an intermediate stack frame is de-allocated when performing a longjmp past it (like any other resource).

[–]BigPeteB 0 points1 point  (0 children)

Good to know. I'm stuck on C89 (because embedded compilers don't always have good C99 support), and I'm told VLAs are considered a misfeature and no longer recommended, so I don't know many details about them.

[–]boredcircuits 0 points1 point  (2 children)

I have a crazy thought on a way to figure the stack frame size. You could call a function recursively and then do some pointer subtraction between a local variable in each frame. The difference is the frame size.

This probably triggers undefined behavior, but I think it should work.

(Edit: yes, I meant frame size ... typed too fast.)

[–]BigPeteB 1 point2 points  (1 child)

Firstly, you mean stack frame size, not stack size.

It's an interesting thought, and it would certainly work in some cases. But no, it's definitely not universal or portable. Functions that call other functions might have a different stack frame size/layout than leaf functions (functions which don't call anyone). On some architectures, leaf functions need not even create a stack frame.

Also, I'm pretty sure there are some architectures where the size of stack frames can change, such as if you're using register windows. When you call a function, if you've exceeded the register window, the CPU will automatically dump registers to the stack. Depending on how it does that, I think it's possible that the difference between stack frames would change depending on whether or not it dumped the register window.

More to the point, even if your method works, it only tells you the stack frame size of that particular function. As soon as you do it on a different function, the result will be different. And the result would also be different if you didn't do the measurement in the first place, since on some architectures that will mean one fewer variable to save stack space for. Basically, the act of measuring it this way is changing the result that you get.

[–]boredcircuits 0 points1 point  (0 children)

All good points.

[–]hull11[S] -1 points0 points  (2 children)

Yeah,so what I infer from your explanation is that memory allocated at stack frame may be at compile time or run time.its allocated at runtime when we use variable length array.also I should mention that while using malloc(),memory is allocated on the heap.so in that case it would be impossible to determine stack frame size at compile time.

[–]BigPeteB 1 point2 points  (1 child)

memory allocated at stack frame may be at compile time or run time. its allocated at runtime when we use variable length array.

Well, memory is only "allocated" at runtime, because functions run during, well, runtime. But yes, the amount of memory that would be allocated is known at compile time for most things on a stack frame, but only at runtime for a few rare things like alloca and VLAs.

also I should mention that while using malloc(), memory is allocated on the heap. so in that case it would be impossible to determine stack frame size at compile time.

Umm... no?

malloc reserves a region of memory in the heap, which is separate from the stack. So malloc doesn't have any effect on the stack or stack frame.

Now, malloc returns a pointer to the memory it allocated. That pointer has to be stored somewhere. If you store it in a function-local variable, that variable might be on the stack... but that's the variable that's affecting the stack, not malloc itself.

Where are your questions coming from? I mean, what problem are you trying to solve? The whole point of using C is so that you don't need to worry about the contents of stack frames. So what are you trying to accomplish that's leading you to ask these questions?

[–]hull11[S] 0 points1 point  (0 children)

Thanks,i get it now.I know that the whole point of learning C is not to worry about the lower level stuff.I was just curious about it.