2016-06-21 19 views
7

Hier ist die Geschichte: Ich entwickle C++ Software für ARM Cortex-M0-Prozessor in Linux mit AC6 Toolpack. Vorher habe ich Keil (in Windows) benutzt (wer hat eine eigene Toolchain) und ich habe auf GNU-toolchain (GNU Tools für ARM Embedded Prozessoren) 5.2.1 migriert. Das erste, was ich realisiert habe, ist; Binärdateigröße wesentlich erhöht. Ich habe alle Compiler-Optimierungen getestet (außer Link-Zeit-Optimierung, es gibt einen Fehler in der Inline-Assembly, nicht Teil der Frage, aber möglicherweise im Zusammenhang mit der Antwort). Dann begann zu prüfen, ausführbare Dateien (Elf-Datei nicht bin, Gnu produziert beide) mit einem Werkzeug zur Verfügung: objdump, readelf, nm. Ich habe einige Symbole gefunden, die eine Größenzunahme verursachen, die wichtigsten sind: 'd_print_comp_inner', 'd_exprlist', 'd_template_args'. Aber haben Sie keine Ahnung, was diese Funktionen im Binärformat verursacht. (Ich habe minimale Bibliotheken verwendet: nano newlib). Lange Rede, kurzer Sinn Ich begann, Codes nacheinander zu eliminieren, um Täter zu finden. Endlich war es die Deklaration der Abstrakten Methode!Deklaration der abstrakten Klasse (reine virtuelle Methode) Erhöhung der binären Größe wesentlich

definieren Funktion als

virtual Return_type function_name(...)=0; 

statt

virtual Return_type function_name(...); 

Hinzufügen von 45 KB und die Symbole ich erwähnt habe. Und das ist die einzige Änderung im Quellcode. Leere Definition in der Basisklasse ist vorhanden. Beachten Sie, dass: Verfahren noch virtuell ist und in untergeordneten Klassen außer Kraft gesetzt

Größe Ausgabe ohne Abstrakte Klasse:

text data  bss  dec  hex filename 
    15316  24 4764 20104 4e88 temc_discovery.elf 

Größe Ausgabe mit abstrakten Klasse:

text data  bss  dec  hex filename 
    61484  128 4796 66408 10368 temc_discovery.elf 

Hier werden die Symbole und ihre Größe, die Wenn die Methode abstrakt ist, werden die in beiden Versionen angezeigten Methoden ausgeblendet. (nm Werkzeug verwendet wird. Nicht vollständige Liste, die, die mit Größe> 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 

Einige Namen vertraut mir (wie printf, bündig, malloc, fputs etc.) sind nicht einmal in der Quelle erwähnt Code.

Jeder mit einer Idee, was dieses Verhalten verursacht?

Update: Ich war bereits Ausnahmen mit Flagge deaktivieren --noexception, so habe ich nicht, obwohl ihm gegeben. Es stellt sich heraus, dass es so gut ist, dies zu erwähnen.

Update 2: This is the most comprehensive website alles erklären, wenn Sie die Links in den Antworten verfolgen.

+0

könnte es besser sein, die Kompilierung und Link-Befehl zur Verfügung zu stellen, zum Beispiel Die '-g' Option erzeugt eine größere Binärzahl für Debug-Symbole, etc. Und Sie können die Größe der entfernten Binärdatei überprüfen. – Mine

+0

Wie ich traurig bin, habe ich alle Compiler-Optimierungen versucht. Gleiches Ergebnis (mit höherem Anstieg 40 KB). – ifyalciner

+2

Lösung. wahrscheinlich, schon hier gegeben: https://stackoverflow.com/questions/14689639/can-i-disable-exceptions-for-when-a-pure-virtual-function-is- – deniss

Antwort

6

Es ist fast sicher wegen der unerwarteten Einbeziehung der Ausnahmebehandlung, die libC++ eingebaut hat, unabhängig davon, ob Sie Ihren Code mit --noexception kompilieren oder was auch immer der richtige Gnu-ism ist.

Die fragliche Ausnahme ist wahrscheinlich 'reiner virtueller Funktionsaufruf' oder etwas ähnliches (ein ziemlich obskurer Laufzeitfehler zu erhalten, aber möglich, wenn Sie virtuelle Funktionen im Basisklassenkonstruktor aufrufen).

Die Antwort ist, Ihre eigene leere Implementierung von dieser, atexit(), und was auch immer zufälliges Callout, das Sie nicht wirklich benötigen. Sobald Sie das tun, wird der Linker nicht in den anderen Sachen ziehen (was andere Sachen schleppt, was andere Sachen schleppt, usw.).

void __cxa_pure_virtual(void) 
{ 
    BKPT(); 
} 

Ist das, was ich an unserem Projekt haben, wenn die Dinge in Ihrer Version von libc verändert haben ++

+0

Danke für die Antwort. Es funktionierte. – ifyalciner

5

Soweit ich verstehe, wenn Sie Ihre virtuelle Funktion in der Basisklasse pure machen Sie schaffen das Potenzial für einen reinen virtuellen Anruf. So erzeugt der Compiler Code, wo er eine Nachricht über reine virtuelle Call-Fakten, entfremdete Namen für Funktion und Klasse und möglicherweise etwas anderes ausgibt. Es fügt Ihrer Binärdatei eine Menge Funktionen hinzu, so dass die Größe zunimmt.

Ich schlage vor, eine leere Implementierung zu Ihrer reinen virtuellen Funktion hinzufügen - möglicherweise verhindert es Compiler von diesem Zeug.

+0

Nur Änderung im Code ist '= 0'. Um nicht 'Funktion nicht definiert Fehler' zu bekommen, habe ich bereits eine leere Definition der Funktion. – ifyalciner

+0

Siehe http://stackoverflow.com/questions/99552/where-do-pure-virtual-function-call-crashes-come-from –

+0

@ifyalciner, Sie können beide = 0 für Funktion und es ist leere Implementierung, z. virtueller Destruktor. – user2807083