Here's the story: I am developing C ++ software for the ARM Cortex-M0 processor on Linux using the AC6 Toolpack. Before I used Keil (in windows) (who have their own toolchain) and I switched to the GNU-toolchain ((GNU Tools for ARM Embedded Processors) 5.2.1). The first thing I realized; the size of the binary file has increased significantly. I tested every compiler optimization (with the exception of link time optimization, it gives an error in the built-in assembly, not in part of the question, but may be related to the answer). Then he began to check executable files (elf file is not bin, gnu produces both) with any tool available: objdump, readelf, nm. I found several characters that cause an increase in size, the significant ones are: ' d_print_comp_inner ', ' d_exprlist ', ' d_template_args '. But I have no idea what causes these functions to appear in binary format. (I used minimal libraries: nano newlib). In short, I began to eliminate codes one by one to find the culprit. Finally, it was an abstract method declaration!
Function definition as
virtual Return_type function_name(...)=0;
instead
virtual Return_type function_name(...);
adding 45 kb and the characters i mentioned. And this is the only change in the source code. There is an empty definition in the base class. Note: the method is still virtual and is overridden in child classes
Output size without an abstract class:
text data bss dec hex filename 15316 24 4764 20104 4e88 temc_discovery.elf
Output size with abstract class:
text data bss dec hex filename 61484 128 4796 66408 10368 temc_discovery.elf
Here the characters and their size, which appears when the method is abstract, eliminate those that appear in both versions. ( nm tool is used. Not a complete list, those with size> = 0x60)
00002de4 t d_print_comp_inner 00001a34 t d_exprlist 00000ca4 t d_template_args 00000678 t d_type 00000574 t d_print_mod 000003f8 t d_encoding 000003e0 r cplus_demangle_operators 000003c8 t d_expression_1 000003a8 t d_name 00000354 t d_demangle_callback.constprop.15 000002e0 t d_print_mod_list 00000294 r cplus_demangle_builtin_types 00000268 t d_unqualified_name 00000244 T _printf_i 00000238 t d_print_function_type.isra.11 000001fc T _svfprintf_r 000001fc T _svfiprintf_r 000001f4 t d_print_array_type.isra.10 000001ce t d_print_cast.isra.12 0000018c t d_substitution 00000110 t d_operator_name 0000010c T __sflush_r 000000e8 T __swsetup_r 000000e6 t d_cv_qualifiers 000000e0 t d_print_subexpr 000000e0 t d_expr_primary 000000dc T _printf_common 000000cc T __cxa_demangle 000000c8 t d_source_name 000000c4 r standard_subs 000000c4 T __ssputs_r 000000b0 T __swbuf_r 000000ac T _malloc_r 000000a8 T _fputs_r 000000a4 T __smakebuf_r 000000a0 T __gnu_cxx::__verbose_terminate_handler() 00000096 t d_print_expr_op 0000008c T _free_r 0000008c t d_parmlist 0000008a t d_growable_string_callback_adapter 0000007c T __sfp 00000072 t d_append_buffer 00000068 T __sinit 00000060 d impure_data
Some names familiar to me (e.g. printf, flush, malloc, fputs, etc.) are not even mentioned in the source code.
Does anyone know what causes this behavior?
Update: I have already disabled exceptions with the --noexception flag, so I have not received any references to it. As it turned out, this is due to the fact that itβs so good to talk about it here.
Update 2: This is the most comprehensive website explaining all this if you are tracking links in the responses.