Reduce stack usage of _vfiprintf_r()

Federico Terraneo
Wed Oct 10 17:09:00 GMT 2012

Hash: SHA1

On 10/10/2012 05:32 PM, Freddie Chopin wrote:
> Hi!
> I'm using newlib on ARM microcontrollers that have limited amount
> of RAM ("few" to "few tens" of kilobytes). Due to design of
> _vfiprintf_r() it's almost unusable for such targets, as static
> function __sbprintf() is inlined into it - sbprintf() has a 1kB
> buffer on stack. This buffer is there for optimizing access to
> unbuffered streams, but my application does not use them and 1kB is
> a tremendous waste of space... If I would be using such buffer,
> there would be a waste of space too, as __sbprintf() recursively
> calls _vfiprintf() which would have a buffered "fake" file now, but
> still allocate 1kB on stack in case it's unbuffered...
> I've changed that for myself to use dynamic allocation like this
> (that's from version 1.19.0):
>> /* * Helper function for `fprintf to unbuffered unix file':
>> creates a * temporary buffer.  We only work on write-only files;
>> this avoids * worries about ungetc buffers and so forth. */ 
>> static int _DEFUN(__sbprintf, (rptr, fp, fmt, ap), struct _reent
>> *rptr _AND register FILE *fp   _AND _CONST char *fmt  _AND 
>> va_list ap) { int ret; FILE fake; unsigned char *buf;
>> /* copy the important variables */ fake._flags = fp->_flags &
>> ~__SNBF; fake._flags2 = fp->_flags2; fake._file = fp->_file; 
>> fake._cookie = fp->_cookie; fake._write = fp->_write;
>> buf = _malloc_r(rptr, BUFSIZ);
>> if (buf == NULL) return EOF;
>> /* set up the buffer */ fake._bf._base = fake._p = buf; 
>> fake._bf._size = fake._w = BUFSIZ; fake._lbfsize = 0;    /* not
>> actually used, but Just In Case */ #ifndef __SINGLE_THREAD__ 
>> __lock_init_recursive (fake._lock); #endif
>> /* do the work, then copy any error status */ ret = _VFPRINTF_R
>> (rptr, &fake, fmt, ap); if (ret >= 0 && _fflush_r (rptr, &fake)) 
>> ret = EOF; if (fake._flags & __SERR) fp->_flags |= __SERR;
>> _free_r(rptr, buf);
>> #ifndef __SINGLE_THREAD__ __lock_close_recursive (fake._lock); 
>> #endif return (ret); }
> I can provide a patch against current trunk if you think this
> solution is reasonable - I hope you do, because such a waste of
> stack on small microcontrollers is unacceptable...
> Regards, Freddie Chopin

first of all, am not a newlib devloper, just a regular user. I noticed
the exact same problem in RAM constrained ARM microcontrollers when
using newlib together with an RTOS that I developed. The solution I
found is different though, and is to apply a simple patch to newlib
that redefines BUFSIZ to 512 instead of 1024. That small change later
became part of a larger patch that can be found here:
The relevant lines are 32--39.
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Mozilla -


More information about the Newlib mailing list