How to calculate the Stack Size?

This is a discussion on How to calculate the Stack Size? within the C Programming forums, part of the General Programming Boards category; There is no trivial way to do that, since each function may or may not save some registers and create ...

  1. #16
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    There is no trivial way to do that, since each function may or may not save some registers and create local temporary variables [1] on the stack, besides the actual parameters and local variables. You would also have to figure out what functions call which functions (which there is code that does), and then figure out which of all the various trees that you could come up with uses the most stack.

    [1] The compiler can create temporary variables to hold the result of some calculation if there isn't a sufficient number of registers available at the time, or if it needs to convert a variable into a different type (e.g. float -> integer, integer -> float).

    You would possibly have more luck with examining the first few bytes of the instruction code to determine how much the stack is reduced by in the start of the function. This combined with an understanding of the call-graph of the application would enable you too determine the stack usage.

    Note also that in an embedded system, you may have interrupt handlers that run asynchronously to the rest of the code, and thus use up stack "anywhere", so you would need to reserve space for the interrupt handlers on top of whatever your application uses.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  2. #17
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,785
    Any code that relies on stack size is also broken.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #18
    Registered User
    Join Date
    Apr 2008
    Posts
    83

    Hai mates

    Quote Originally Posted by matsp View Post
    There is no trivial way to do that, since each function may or may not save some registers and create local temporary variables [1] on the stack, besides the actual parameters and local variables. You would also have to figure out what functions call which functions (which there is code that does), and then figure out which of all the various trees that you could come up with uses the most stack.

    [1] The compiler can create temporary variables to hold the result of some calculation if there isn't a sufficient number of registers available at the time, or if it needs to convert a variable into a different type (e.g. float -> integer, integer -> float).

    You would possibly have more luck with examining the first few bytes of the instruction code to determine how much the stack is reduced by in the start of the function. This combined with an understanding of the call-graph of the application would enable you too determine the stack usage.

    Note also that in an embedded system, you may have interrupt handlers that run asynchronously to the rest of the code, and thus use up stack "anywhere", so you would need to reserve space for the interrupt handlers on top of whatever your application uses.

    --
    Mats

    Hai Mats,
    Is there any way to try during Run time? So that we will get accurate size

  4. #19
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,211
    Someone tell him the answer in big bold letters. He apparently doesn't read normal text.

  5. #20
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,785
    Quote Originally Posted by shwetha_siddu View Post
    Hai Mats,
    Is there any way to try during Run time? So that we will get accurate size
    NO!
    There is no reliable way to do this.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #21
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,211
    Thank you, Elysia.

  7. #22
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Actually, I believe it's EASIER to determine this during runtime, using a method like what I posted. It is VERY difficult to do as a "process the source code as text", because you will not be able to determine what the compiler does to the code, even if you can calculate the exact size of each variable on the stack [1].

    However, you may want to use the OS/C Runtime to fill the stack before it calls main - assuming you have access to the stack creation source code that is. Then you could fill the stack with a predetermined pattern that can be checked, without having to deal with "safety margins" like I do in my example (as we don't know exactly how much of the stack has been used up before we get to main).

    [1] Note that we have so far only discussed the usage of simple variables. How would you write code that figures out the size of a struct that has several different fields of different size and perhaps differnet alignment criteria, other structs inside the first struct, unions etc, etc. What about variables declared deeper inside a function (It is valid to declare variables inside if-statements, case-statements, or any other block surrounded by curly braces). Essentially, to statically analyze this sort of problem, you would really need a parser that understands the C code almost completely. It wouldn't be a full compiler, but it would have to understand types, functions, function parameters and blocks within functions. And you would have to be able to build the call-stack down to leaf functions.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #23
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,785
    Quote Originally Posted by matsp View Post
    Actually, I believe it's EASIER to determine this during runtime, using a method like what I posted. It is VERY difficult to do as a "process the source code as text", because you will not be able to determine what the compiler does to the code, even if you can calculate the exact size of each variable on the stack [1].
    But it still isn't 100% reliable, so as stated, it's not entirely reliable.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #24
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    But it still isn't 100% reliable, so as stated, it's not entirely reliable.
    Explain what part of it is not reliable? [Assuming we choose a fill pattern that is not commonly used in large data blocks in the code, that is].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #25
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,785
    I don't propose to understand your code (I don't), so you tell me if it works on every system and it gives an accurate answer.
    If it works across all platforms, then sure it's reliable, but if it doesn't, then it's not reliable.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #26
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by Elysia View Post
    I don't propose to understand your code (I don't), so you tell me if it works on every system and it gives an accurate answer.
    If it works across all platforms, then sure it's reliable, but if it doesn't, then it's not reliable.
    You are correct, if portability is your definition of reliable then I guess there are some considerations:
    • As the comment in the code is indicating, it wouldn't work without modification on a system where the stack grows towards higher numbers - I do not know of any system where stack is growing towards higher numbers, but I'm sure there is one somewhere [actually, I have a feeling 6502 may have such a stack - I can't quite remember]. It wouldn't be very difficult to make it work on such a system - essentially just reverse the add and subtract operations in the current code.
    • It also would only work on the "memory stack" in processors that have separate register and memory stacks (such as 29K), since you can't take the address of the register stack from code by taking the address of a local variable (a local variable is always on the memory stack). I consider this a minor misfeature, as you are much more likely to run out of the memory stack [large variables, such as arrays and structs bigger than 2 x 32 bits, always go on the memory stack in 29K code] than the register stack.


    I'm sure there are other obscure architectural features that would make it not work - but I can't think of those.

    It relies on the stack being used being writable, which is should always be and that it's present/available [which it isn't always in Windows, it appears like the first two pages (8KB) of stack is immediately available, the rest of it needs to be allocated by growing the stack pointer beyond that - so if we wanted to use this in a system that uses a lot of stack in Windows [and most likely Unix/Linux], we'd need a function like this:
    Code:
    inline void growTheStack()
    {
        volatile int array[FILLSIZE / sizeof(int)];
        array[0] = 0;
        array[(FILLSIZE / sizeof(int)) -1] = 0;
    }
    I added the volatile to prevent the compiler from optimizing the entire array away and doing nothing.

    Aside from those concerns, I wouldn't call it "unreliable" - but you are right that it would not be completely portable to all types of architectures.


    --
    Mats
    Last edited by matsp; 06-25-2008 at 07:03 AM.
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #27
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,785
    Quote Originally Posted by matsp View Post
    Aside from those concerns, I wouldn't call it "unreliable" - but you are right that it would not be completely portable to all types of architectures.
    Even so, reliable or not, no well written code relies on the size of the stack.
    I don't even think there is a "stack" mentioned in the C standard.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  13. #28
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    That's because it's implementation specific (nothing really to do with C). No-one said the arch has to use a stack at all, in fact I think there were some that didn't (pretty rare).

    Of course that could be some story my brain made up to make me feel happy.

  14. #29
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,785
    And this is why it cannot be guaranteed to work or work properly, and so should be avoided IMHO.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #30
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If you want 100% portability, then you can't rely on there being a stack, that is correct. I know of no machine that doesn't have one, but that's no excuse for assuming that there is one.

    But then if you want to calculate the size of the stack, we can presume this is because there is a (single?) stack for one process.

    You also can't say "no code should rely on the size of the stack". That essentially means:
    1. No local variables.
    2. No nested calls (or function calls at all).
    3. No parameters to the non-existing function calls.
    Because all calls to other functions [with the possible exception in some architectures of leaf-functions, where the stack is not being used].

    If you mean that "no code should rely on KNOWING the size of the stack", then I would agree - but you then have to assume that it is big enough for what you want to do. And in an embedded system, the stack may well be in the kilobytes rather than megabytes range.

    In an embedded scenario, it would definitely be useful to know if we are very close to going over the edge of the stack (there may also be no hardware protection of the stack if the machine isn't using virtual memory - since there is no page-table to indicate that the end of stack is "forbidden area").

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Page 2 of 3 FirstFirst 123 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Stack Implementation and Exceptions
    By audinue in forum C Programming
    Replies: 4
    Last Post: 06-22-2008, 09:32 AM
  2. Error with a vector
    By Tropicalia in forum C++ Programming
    Replies: 20
    Last Post: 09-28-2006, 07:45 PM
  3. stack and pointer problem
    By ramaadhitia in forum C Programming
    Replies: 2
    Last Post: 09-11-2006, 11:41 PM
  4. Invalid conversion from 'void*' to 'BYTE' help
    By bikr692002 in forum C++ Programming
    Replies: 9
    Last Post: 02-22-2006, 10:27 AM
  5. Replies: 11
    Last Post: 03-25-2003, 04:13 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21