bugAVR C Runtime Library - Bugs: bug #50811, using -Wl,-u,vfprintf -lprintf_min...


bug #50811: using -Wl,-u,vfprintf -lprintf_min causes program to grow a lot

Submitted by:  None
Submitted on:  Sat 15 Apr 2017 11:38:22 PM UTC  
Category: NoneSeverity: 3 - Normal
Priority: 5 - NormalItem Group: None
Status: NonePercent Complete: 0%
Assigned to: NoneOriginator Email: -unavailable-
Open/Closed: OpenRelease: 2.0.0
Fixed Release: None

Add a New Comment(Rich Markup)

You are not logged in

Please log in, so followups can be emailed to you.


(Jump to the original submission Jump to the original submission)

Tue 09 May 2017 08:55:01 PM UTC, comment #9:

Re. the "compiler thing" mentioned above:

avr-gcc might replace a call to printf by a call to puts provided the arguments of printf allows to do so. You can avoid this optimization by means of -fno-builtin-printf which takes away any knowledge (except prototype information) about printf from the compiler. This will result in a call to printf (which you are using anyway), saving the call to fputs.

Georg-Johann Lay <gjlayde>
Tue 18 Apr 2017 06:02:58 AM UTC, comment #8:

> I guess maybe it happens inevitably due to compiler
> machinations.

Exactly, it's a compiler thing we cannot influence.

Joerg Wunsch <joerg_wunsch>
Project Administrator
Mon 17 Apr 2017 09:04:22 PM UTC, comment #7:

If that's the case, why provide an optimized version of printf() for constant strings at all? I guess maybe it happens inevitably due to compiler machinations.

Anyway, at least one person (me) hit this issue and it took me some time to find the culprit. I set LDFLAGS for the printf_min long ago with the idea of generally keeping program size low, and this turns out to be a very poor general policy. The current docs don't give any indication of this, while they do describe smaller savings related to vfprintf choice in the presence of printf(). That's inconsistent and somewhat misleading.

Mon 17 Apr 2017 08:07:54 PM UTC, comment #6:

Well, the fact that the -u vfprintf needs to be forced is
an unfortunate side effect of libprintf_min.a only containing
a different definition of vfprintf(), but not e.g. for printf()
or other members of the family.

Thus, if you only add -lprintf_min, this library will be
processed by a time when the linker has not seen any obvious
need to drag the vfprintf symbol in from it, so in effect, it
will be ignored. Later on, when it comes to resolve the
symbols needed by (e.g.) printf, it will suddenly also need
vfprintf, but libprintf_min.a is already done by that time,
so the standard version of vfprintf is used (from libc.a).

We could probably reorganize these libraries to also contain
the other printf family members, but 1) that needs to be done
by someone (who?), and 2) it won't fix the history, so the
documentation has to remain the way it is for at least a
while (a couple of years or more).

While the complaint this bug is focussing on is not
completely invalid, I think it's practically a non-issue:
except for the degraded testcase, nobody would want to drag
in the full power (and bloat) of printf() & co. if all he
wants to do is printing some constant strings without using
any of the formatting functionality. As soon as a real
printf functionality is needed, as seen, there is indeed a
minimal saving of space by libprintf_min.a.

Joerg Wunsch <joerg_wunsch>
Project Administrator
Mon 17 Apr 2017 07:19:55 PM UTC, comment #5:

I guess my point is that this statement (by itself) is false:

"Note that if your program doesn't end up calling vfprintf(), using the printf_min linker flags will increase code size because it forces the vfprintf() function to be included even though it isn't used."

It's only when both options are used together that you get that behaviour.

I think using -Wl,-u,vfprintf is incorrect and there is no need to use that option unless you want to keep unused code in your image.

Personally, I'd find the behaviour of keeping unused code in the image to be the confusing behaviour, not the fact that my debug builds are considerably larger than my release builds.

Dave Hylands <dhylands>
Mon 17 Apr 2017 06:54:57 PM UTC, comment #4:

You're correct, there's no reason when printf isn't being used to use those linker options. However:

  • realistically at least some linker options are at least somewhat black magic to many users.
  • printf() is particularly likely to go from unused to used during debugging, during which large swings in code size may be extra confusing

For these reasons, I still think adding something to the documentation would make sense. It could be as simple as one sentence explaining what you just explained:

"Note that if your program doesn't end up calling vfprintf(), using the printf_min linker flags will increase code size because it forces the vfprintf() function to be included even though it isn't used."

Mon 17 Apr 2017 04:46:35 PM UTC, comment #3:

Using _Wl,-u,vfprintf is essentially forcing the symbol vfprintf to be undefined and added to the program. This is what's causing your code size to increase when not otherwise using vfprintf.

It isn't clear to me why that option should be required at all. You should only need to add the -lprintf_min option and that will pull in vprintf, if its used, and won't pull anything in if it isn't.

Dave Hylands <dhylands>
Mon 17 Apr 2017 06:18:07 AM UTC, comment #2:

Ok, with printf("foo: %d\n, 42), the program is indeed smaller with by 264 bytes when -Wl,-u,vfprintf -lprintf_min is used than when none of the printf linker flags are used.

I guess this is a wishlist item really: it would be nice if using printf_min didn't end up adding 1000 or so bytes to the program size when variadic vfprintf() invocations don't happen at all.
I suppose given the realities of how the linker works that's unlikely. At least the issue deserves a mention in the discussion of these options in the vfprintf() documentation (that they can end up making your program a lot bigger, rather than smaller).

Sun 16 Apr 2017 09:11:13 PM UTC, comment #1:

Calling printf("foo\n"); will be optimized to puts("foo"); so your test isn't really valid.

Try omparing a program which uses printf("foo: %d\n", 42); instead.

Dave Hylands <dhylands>
Sat 15 Apr 2017 11:38:22 PM UTC, original submission:

The documentation seems to be saying that using those flags is supposed to save flash, but without them, a main() that does a single printf("foo\n"); gives me a 330 byte flash, while with them I get a 1330 byte flash.

If I remove the printf() call, I get flash sizes of 1228 or 228 with or without the above mentioned printf-min flags, respectively.

It looks like somehow the printf-min flag ends up dragging in a bunch extra code somehow?

The rest of my linker invocation looks like this:

avr-gcc -mmcu=atmega328p -lm -Wl,-gc-sections -Wl,-Map=program_to_upload.out.map -o program_to_upload.out main.o

I think probably the documentation ought to mention this possibility, assuming it isn't a bug.



(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach File(s):

No files currently attached


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -unavailable- added by gjlayde (Posted a comment)
  • -unavailable- added by joerg_wunsch (Posted a comment)
  • -unavailable- added by dhylands (Posted a comment)
  • -unavailable- added by None (Submitted the item)

    Please enter the title of George Orwell's famous dystopian book (it's a date):



    No Changes Have Been Made to This Item

    Back to the top

    Powered by Savane 3.1-cleanup1