Reputation: 1019
With reference to this question:
On an embedded project for a small micro I found my compiled code size was much larger than expected. It turned out it was because I had included code that used assert(). The use of assert was appropriate in the included code but caused my compiled code size to almost double.
The question is not around if/when assert should be used but how the compiler/linker decides to include all the necessary overhead for assert.
My original question from the other post:
It would be helpful if someone could explain to me how gcc decides to include library functions when assert is called? I see that assert.h declares an external function __assert_func. How does the linker know to reference it from a library rather than just say "undefined reference to __asert_func"?
Upvotes: 4
Views: 3379
Reputation: 229108
When configuring a toolchain, the authors decide which libraries that should be linked to by default.
Often this is includes runtime startup/initializing code and a library named libc
which includes an implementation of the C standard, and any other code the authors deem relevant (e.g. libc might also implement Posix, any custom board specific functions etc.) and for embedded targets it's not unusual to also link to a library implementing an RTOS for the target.
You can use the -nodefaultlibs
flag to gcc to omit these default libraries at the linking stage.
In the case of assert(), it is a standard C macro/function , which is normally implemented in libc. assert() might print to stdout
if it fails, so using assert() could pull in the entire stdio facility that implements FILE* handling/buffering, printf etc., all which is implemented in libc.
You can see the libraries that gcc links to by default if you run gcc -v
for the linking stage.
Upvotes: 8
Reputation: 119877
On your embedded system linking is static. Static linking works as follows.
A static library is an archive of object files. The linker considers each object separately.
A referenced function or variable that is found in a static library is included in the resulting executable, together with the entire object file that contains the referenced symbol. Object files that don't contain referenced symbols are not pulled in.
This isn't by any way specific to gcc. Linkers work this way since the dawn of time.
Upvotes: 3
Reputation: 1
The gcc
(or g++
) command is simply a driver. It runs other programs, including the compiler proper (cc1
for C code, cc1plus
for C++ code) and the assembler and the linker.
What programs are run are determined by the spec file (and there is an implicit one, see the -dumpspecs
developer option). BTW, running gcc
with the -v
option displays the actual programs involved.
The assert
macro is defined (see file /usr/include/assert.h
) to do some check in <assert.h>
only if NDEBUG
is not a defined preprocessor symbol. On my Linux/Glibc system it can call a __assert_failed
internal function from the C standard library. Citing assert(3) documentation:
If the macro
NDEBUG
is defined at the moment<assert.h>
was last included, the macroassert()
generates no code, and hence does nothing at all.
Some projects are compiling with -DNDEBUG
their code in production mode.
You should read the Invoking GCC chapter of the documentation.
Perhaps you want to compile with -ffreestanding
to avoid any extra libraries, even the standard ones?
Upvotes: 5