Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.arch.embedded > #28791

Re: No dynamic memory at all: newlib and sprintf

From David Brown <david.brown@hesbynett.no>
Newsgroups comp.arch.embedded
Subject Re: No dynamic memory at all: newlib and sprintf
Date 2019-09-02 13:09 +0200
Organization A noiseless patient Spider
Message-ID <qkit9b$tt7$1@dont-email.me> (permalink)
References (3 earlier) <qkantj$ao8$1@dont-email.me> <qkb4bc$fea$1@dont-email.me> <qkb8v7$bt3$1@dont-email.me> <qkhapc$ica$1@dont-email.me> <qkhelh$a7g$1@dont-email.me>

Show all headers | View raw


On 01/09/2019 23:53, pozz wrote:
> Il 01/09/2019 22:47, David Brown ha scritto:
>> On 30/08/2019 15:39, pozz wrote:
>>> Il 30/08/2019 14:21, pozz ha scritto:
>>>> Il 30/08/2019 10:48, David Brown ha scritto:
>>>  >[...]
>>>> However I tried to replace sprintf() with a custom sprintf(), but in
>>>> this case the linker complains with:
>>>>
>>>>    multiple definition of `sprintf'
>>>>
>>>> It sees two definitions in my printf.c and in libc_nano.a. Could you
>>>> argue why this happens with sprintf() and not with malloc()?
>>
>> Are you sure?  Have you checked the map file (and given the linker
>> settings for showing detailed information in the map file) ?
>>
>>>
>>> After seen that -O1 linker option solves this problem, I found the
>>> option
>>>
>>>    --allow-multiple-definition
>>>
>>> that works even with -O0, that I use in debug build.
>>>
>>
>> It seems risky to allow multiple definitions.  It's not an option I
>> have used - I'd need to look more deeply into documentation before I
>> can be more helpful.
> 
> You're right, but it is the only solution I found to replace standard
> pritnf with a custom implementation.
> 
> 
>> I never recommend using -O0, for any purpose.  Code at -O1 (on gcc at
>> least) is much easier for debugging, with far clearer assembly.  More
>> importantly, it enables a lot more analysis on the compiler and
>> therefore gives far more accurate static warnings.
> 
> much easier... far clearer... a lot more analysis... far more
> accurate... than what? Are you comparing -O1 with -O0?

Yes.  Compare the generated assembly codes, and see which optimisation
gives you code that is easiest to follow.  (The "more analysis" and
"more accurate warnings" bits I hope you agree with.)

> 
> 
>> I usually compile at approximately -O2 
> 
> for production/release build? For this I use -Os, because many times I
> have small Flash memory.

I find that often, -Os makes little difference in code size compared to
-O2.  Sometimes it is even smaller.  But that does vary a bit between
targets, and also according to the type of code you write.

And remember that the size of the flash and the size of the program is
not the important issue.  What is important is that the program fits in
the flash, perhaps with some space for future changes to the code.  If
you have a little microcontroller with 8K flash, then a 7K program that
runs 1% faster, can sleep 1% longer, and therefore has 1% more battery
life, is /better/ than a 3K program that is 1% slower.

> 
> 
>> (by "approximately", I mean I often have some additional specific
>> flags added).  It can make single-step debugging difficult because it
>> re-arranges code a lot, so occasionally I will go down to -O1 for a
>> file if I need to use a lot of single-step or assembly level debugging
>> on it.
>>
>> I am strongly against the whole concept of "debug build" and "release
>> build" if it encourages you to use different optimisation levels and
>> settings.  
> 
> Why? Debug buil is used for... debug, usually during developing. It's
> much easier to debug with -O0 than -O2 or -O1.
> 

No, it is not.  Single-stepping through -O2 can be confusing as code
jumps around a bit, but -O1 is fine for that.  And if you are doing a
lot of single-stepping debugging, you might want to think about your
development process to see if it can be made more efficient.  (There is
never one right answer, and I don't want to give that impression - in
this business, there is always a great amount of variation.  I can only
talk about generalities, and my own experiences.)

With -O0 compiles, gcc puts (almost) everything on the stack.  The
assembly code for even simple operations is horrible - there are many
times as many instructions as needed.  This makes it very difficult to
follow what is being done.  And it is totally unrealistic in terms of
performance and code size from "real" complied code.

-O1 compiles generate code that is simpler and neater.  -O2 has similar
code generation in many cases, but does far more re-arrangement and
re-ordering, which can make debugging difficult.


A big problem with -O0 for "debug builds" that I have seen, is people
get the wrong impression of their code.  They write code that looks okay
to them, but is in fact bad - they have misunderstood pointer aliasing,
missed out essential "volatile", relied on integer overflow wraps, and
all sorts of other mistakes.  They do all their testing and debugging
with -O0.  Then for the "release" build, they have -O1 or -O2 (or -Os),
their asserts and run-time checks are disabled, and their test code is
removed - they compile and use their "working" and "tested" code.  And
then things go subtly wrong in ways they don't understand or expect,
since the code is "tested".  It is classic "it worked when I tested it"
code, and is the cause of a lot of problems people have.

Remember - test what your ship, ship what you test.  Splitting "debug"
and "release" builds just doubles your workload for all your testing and
debugging.

> 
>> Enabling or disabling verbose outputs for different bits of the code
>> is okay.
> 
> Yes, this is another goal of debug build (enabling a serial port for
> some outputs). And I usually disable watchdog in debug buid, because
> watchdog doesn't work well during debugging.
> 

Watchdogs don't work well in release either - at least, not for what
many people seem to think they should do.  But they cause more problems
during debugging.

Back to comp.arch.embedded | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread


Thread

No dynamic memory at all: newlib and sprintf pozz <pozzugno@gmail.com> - 2019-08-30 09:29 +0200
  Re: No dynamic memory at all: newlib and sprintf David Brown <david.brown@hesbynett.no> - 2019-08-30 09:57 +0200
    Re: No dynamic memory at all: newlib and sprintf pozz <pozzugno@gmail.com> - 2019-08-30 10:23 +0200
      Re: No dynamic memory at all: newlib and sprintf David Brown <david.brown@hesbynett.no> - 2019-08-30 10:48 +0200
        Re: No dynamic memory at all: newlib and sprintf pozz <pozzugno@gmail.com> - 2019-08-30 14:21 +0200
          Re: No dynamic memory at all: newlib and sprintf pozz <pozzugno@gmail.com> - 2019-08-30 15:39 +0200
            Re: No dynamic memory at all: newlib and sprintf David Brown <david.brown@hesbynett.no> - 2019-09-01 22:47 +0200
              Re: No dynamic memory at all: newlib and sprintf pozz <pozzugno@gmail.com> - 2019-09-01 23:53 +0200
                Re: No dynamic memory at all: newlib and sprintf David Brown <david.brown@hesbynett.no> - 2019-09-02 13:09 +0200
    Re: No dynamic memory at all: newlib and sprintf pozz <pozzugno@gmail.com> - 2019-08-30 10:35 +0200
  Re: No dynamic memory at all: newlib and sprintf Paul Rubin <no.email@nospam.invalid> - 2019-08-30 01:46 -0700
  Re: No dynamic memory at all: newlib and sprintf Dave Nadler <drn@nadler.com> - 2019-08-30 06:17 -0700

csiph-web