library stack usage

Go To Last Post
15 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi All,

Is it documented anywhere how much stack is used by the various C library routines? I have discovered (the hard way!) that the floating point version of sscanf() uses a lot of stack (seems to be something like 100 bytes).

Thanks,

Christopher Hicks
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think it highly unlikely that you will find library stack usage documented.

You can always compile, and then trace the code in the Studio simulator. I am not sure about avr-gcc, but CodeVision calculates your exact stack usage.

If you are one of the few people that read documentation, I would have thought that you would have found better alternatives than scanf().

Personally I cannot be bothered to trace sscanf() myself. But I would put money on the stack usage being less than 100 bytes.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

One of the joys of GCC and the avr-libc runtime library are that they are open source so it's no secret how they operate - just pull the source for sscanf and you can see how it operates. In fact you can build the source into your own project rather pulling the library function at link time and even source level debug it if you want (the C bits).

Cliff

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
But I would put money on the stack usage being less than 100 bytes.

Fair enough, you'd win your bet. The following call to sscanf:

const char p[] = " 10.00 11.00";
float f1, f2;
sscanf(p, "%f %f", &f1, &f2);

uses 68 bytes of stack on the version of the libraries I am using. I remain surprised by that, but I can accept it. I guessed the 100 bytes figure on the basis of circumstantial evidence at the end of a long day yesterday - I knew it was more than 64 but less than 128!

The point that the source is open, tried and well tested is well made and taken. You may be right as to alternatives to scanf and friends. A call to atof() seems to use only about 20 bytes of stack.

But that wasn't really my point, which was actually that the experience with sscanf() made me wonder about the stack usage of other bits of the library.

Christopher Hicks
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

At the risk of sticking my neck out, I would say that all library functions with the exception of scanf() and printf() probably use less than about 8 bytes of stack.

Some library functions may have a static area (which is not using the stack).

Some library functions will call other library functions, and the nesting will be additive.

And I suspect that qsort() will be mildly recursive.

But most of the time embedded programming will never have any stack problems. Just use common sense. Never use scanf().

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

cmhicks wrote:

const char p[] = " 10.00 11.00";
float f1, f2;
sscanf(p, "%f %f", &f1, &f2);

uses 68 bytes of stack on the version of the libraries I am using.

I tested it and without sscanf I get only 6 bytes less:

    4.3.0
    text data bss dec hex filename
    3110 20 8 3138 c42 test.out

    4.3.0
    text data bss dec hex filename
    3014 14 8 3036 bdc test.out

The remaining 14 bytes are used by p[].

I use the linker switch:

-Wl,-u,vfscanf -lscanf_flt -lm

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

danni wrote:

I tested it and without sscanf I get only 6 bytes less:

    4.3.0
    text data bss dec hex filename
    3110 20 8 3138 c42 test.out

    4.3.0
    text data bss dec hex filename
    3014 14 8 3036 bdc test.out

That's surely static data usage, not runtime stack depth.

Quote:

Some library functions will call other library functions, and the nesting will be additive.

This seems to be the nub of the matter. The call nesting depth is significant in the case of sscanf(), and because it has a variable argument list (and the va_list is passed up the call chain), all parameters are passed on the stack, and re-stacked at each function call level.

Quote:

But most of the time embedded programming will never have any stack problems.

That may or may not be true. When developing high-reliability code I personally like to know the worst-case stack depth. This especially the case when running an RTOS and wanting to share relatively small amounts of RAM amongst two or three or four tasks' stacks.

I am fairly new to the AVR (and the GNU-based libraries for it), but having had years of previous experience with Motorola, 8051 and ARM processors, all using commercial libraries. I don't usually use scanf and friends as it happens; in fact I avoid library calls altogether as far as possible, precisely because of issues like this. I just go bitten by it on Saturday and it made me think about the library in general.

CH

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

That may or may not be true. When developing high-reliability code I personally like to know the worst-case stack depth. This especially the case when running an RTOS and wanting to share relatively small amounts of RAM amongst two or three or four tasks' stacks.

Well if you want complete visibility either look at the library source or (probably better) implement your own sscanf() as you say.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I am fairly new to the AVR (and the GNU-based libraries for it), but having had years of previous experience with Motorola, 8051 and ARM processors, all using commercial libraries. I don't usually use scanf and friends as it happens; in fact I avoid library calls altogether as far as possible, precisely because of issues like this. I just go bitten by it on Saturday and it made me think about the library in general.

Since you have the experience, I am surprised that you were bitten.

1. you are aware of microcontroller resource limitations
2. avr-libc source code is freely available.
3. you can trace the code in a Simulator.

It is generally wise to make use of fully debugged standard functions rather than write from scratch.

But the major surprise is in attempting to use such an inappropriate function.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Since you have the experience, I am surprised that you were bitten.

Well, none of us is perfect...

In the time since I posted my question I have not only examined the source and traced it in simulation, but I have posted back my findings in the hope that they will be useful to others.

I completely agree that it is "generally wise to make use of fully debugged standard functions rather than write from scratch" hence my initial decision to use a set of pre-tested string parsing routines from the library rather than write my own. I know plenty about sscanf and were it not for the stack usage issue (which is a matter of implementation, not functionality) it would fit my present needs very well.

I'm afraid I find it mildy offensive that you feel able to judge the appropriateness or otherwise of my decisions without knowledge of the context in which they are made.

CH
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorry, Christopher.

I just have an obsessive dislike of the scanf() family. Please do not take it personally.

Yes, I have used it to read back formatted data from a file. It does an excellent job for that. But if humans are involved, I feel that it is never very easy or secure.

Returning to the original post. I have never seen stack usage documented for any library. The best I have ever seen is advice about recursion or use of static structures.

I have not looked at the scanf() source, but can only guess that there is some recursion involved. Parsing numeric strings can be very elegant by using recursion. IMHO this would be inappropriate for a microcontroller.
There is always an iterative alternative.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just for info, the avr-libc sscanf() source starts here:

http://cvs.savannah.gnu.org/view...

but that just shows that all the work is actually done in vfscanf:

http://cvs.savannah.gnu.org/view...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David,

All agreed, matter closed, and happy again!

CH
==

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After a brief look at the source that Cliff kindly supplied a link for, it appears that there are no recursive calls here.

So I have been talking out of my bottom yet again.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
After a brief look at the source that Cliff kindly supplied a link for, it appears that there are no recursive calls here.

That's the conclusion I reached too. But sscanf() does call vfscanf(), so there is a nested call with a va_list and, without having delved too deeply into how the variable length argument lists are implemented, I think it is the nesting combined with the va_list that results in large stack usage.

CH
==