Unfortunately, you may well have to use xprintf much more generally, (or else check all *printf return values) if you care about robustness under low-memory conditions.
This is because the printf, fputs, fwrite, etc. functions (at least glibc-based functions) always allocate memory upon stream initialization. The first output appears to cause allocation of a 4KB block (a page). I want to know if that first stream output operation can fail without setting the stream error indicator. I tried to provoke this, to see if a failure of that precise allocation would provoke an ferror-detectable failure, but ran into something else. When that particular mmap call fails (I think it's the one in filedoalloc.c from the ALLOC_BUF macro), it ends up causing a segfault 5 or 6 levels up the stack: $ printf '#include <stdio.h>\nint main(){printf("foo");return 0;}\n' > k.c $ gcc -g -Wall -W -O k.c $ gdb -q ./a.out Using host libthread_db library "/lib64/libthread_db.so.1". (gdb) b printf Function "printf" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (printf) pending. (gdb) r Starting program: /t/a/a.out Breakpoint 2 at 0x3c5084ca00 Pending breakpoint "printf" resolved Breakpoint 2, 0x0000003c5084ca00 in printf () from /lib64/libc.so.6 (gdb) b mmap64 Breakpoint 3 at 0x3c508d18d0 (gdb) c Continuing. Breakpoint 3, 0x0000003c508d18d0 in mmap64 () from /lib64/libc.so.6 (gdb) ret -1 Make selected stack frame return now? (y or n) y #0 0x0000003c508613db in _IO_file_doallocate_internal () from /lib64/libc.so.6 (gdb) c Continuing. Program received signal SIGSEGV, Segmentation fault. 0x0000003c5086c8dc in _IO_new_file_overflow () from /lib64/libc.so.6 (gdb) bt #0 0x0000003c5086c8dc in _IO_new_file_overflow () from /lib64/libc.so.6 #1 0x0000003c5086ec34 in _IO_default_xsputn_internal () from /lib64/libc.so.6 #2 0x0000003c5086d881 in _IO_new_file_xsputn () from /lib64/libc.so.6 #3 0x0000003c50842f50 in vfprintf () from /lib64/libc.so.6 #4 0x0000003c5084ca9a in printf () from /lib64/libc.so.6 #5 0x00000000004004cb in main () at k.c:2 (gdb) This is not totally fair, because while I made mmap64 return -1, I did not set errno, which would normally happen for a real failure. I tried, but __errno_location() returns an invalid address. Anyone know how to set errno via gdb? Same thing happened when I compiled with -ggdb3. This is on fedora rawhide, but I got a segfault on debian unstable, too.