Warum sind nicht verwendete Funktionen im Build enthalten?

Gast #3361085
Lesenswert?

Hallo,

ich habe das Problem, dass auch nicht verwendete Funktionen im Build 
enthalten sind und somit das HEX-File aufblächen.
Beispiel:
Ich lege eine Testfunktion an, welche ich niemals aufrufe:
1
#if 1 //0
2
void test_fkt(void);
3
void test_fkt(void)
4
{
5
}
6
#endif

Anschließend compile ich mein Projekt einmal mit aktiver Testfunktion 
(#if 1) und einmal mit abgeschalteter Testfunktion (#if 0).
Die Consolenausgabe gibt unterschiedliche Programmgrößen für mit und 
ohne Testfunktion an:
1
Mit Testfunktion: ... Program: 1056 bytes (3.2% Full) (.text + .data + .bootloader) ...
2
Ohne Testfunktion: ... Program: 1054 bytes (3.2% Full) (.text + .data + .bootloader) ...

Es sind zwar nur 2 Byte, aber es handelt sich ja auch um eine leere 
Testfunktion.
Dabei ist es egal welche Optimierungsstufe ich wähle (-o0, -o1, -o2, 
-o3, -os), es gibt immer einen Programmgrößenunterschied zwischen mit 
und ohne Testfunktion.
Die Dateigröße vom hex-File ändert sich auch.

Des Weiteren taucht die Testfunktion auch im map-File auf:
1
...
2
0x00000094  testfkt1
3
0x0000009a  test_fkt_damit_mehr_speicher
4
0x0000009c  test_fkt2
5
...

Somit spricht meines erachtens alles dafür, dass die Funktion wirklich 
im hex-File enthalten ist.

Meinem Verständnis nach sollte der Linker nicht benötigte Funktionen 
jedoch entfernen. Ich habe nämlich das Problem, dass mein Projekt nicht 
mehr in den µC passt, weil nicht benötigte Funktionen Platz "wegnehmen". 
(Ich möchte nicht alle möglichen Funktionen in meinen Dateien und 
Bibliotheken auskommen.)

Ich hoffe, ihr könnt mir weiterhelfen.

Ich verwende ATmega32, winAVR, Eclipse, Win7 64Bit.

Gruß
Ben
Gast #3361191
Lesenswert?

Ich verwende die entsprechenden Parameter (Einstellungen in Eclipse), 
siehe Aufruf in Console von Eclipse:
1
avr-gcc -Wall -Os -fpack-struct -fshort-enums -ffunction-sections -fdata-sections -std=gnu99 -funsigned-char -funsigned-bitfields -mmcu=atmega32 -DF_CPU=3686400UL -MMD -MP -MF"trunk/PROJECTS/TEST2/TEST2.d" -MT"trunk/PROJECTS/TEST2/TEST2.d" -c -o "trunk/PROJECTS/TEST2/TEST2.o" "E:/trunk/PROJECTS/TEST2/TEST2.c"
2
avr-gcc -Wl,-Map,test2.map --gc-sections -mmcu=atmega32 -o "test2.elf" ...
Nun werden die Funktionen aus gleichen Dateien in unterschiedliche 
Sections aufgeteilt. Aber es werden keine Sections weggelassen.

Map-File:
1
...
2
 .text.testfkt1
3
                0x00000098        0x2 ./trunk/PROJECTS/TEST2/TEST2.o
4
                0x00000098                testfkt1
5
 .text.test_fkt_damit_mehr_speicher
6
                0x0000009a        0x2 ./trunk/PROJECTS/TEST2/TEST2.o
7
                0x0000009a                test_fkt_damit_mehr_speicher
8
 .text.test_fkt2
9
                0x0000009c       0x4a ./trunk/PROJECTS/TEST2/TEST2.o
10
                0x0000009c                test_fkt2
11
...

Hat jemand eine Idee, woran das liegen kann?
Gruß
Ben
Gast #3361223
Lesenswert?

A. K. schrieb:
> --gc-sections
>    !=
> -Wl,--gc-sections

Ich bin mir sehr sicher, dass ich das schon einmal so probiert hatte - 
ohne Erfolg.

Jetzt habe ich es noch einmal so getestet und jetzt funktioniert es. 
(Muss ich wohl noch etwas falsch gemacht haben.) SUPER!
Vielen Dank an euch! Gute Nacht
Ben
Gast #3364356
Lesenswert?

Hallo,

ich bin es noch einmal...
Nun habe ich das Problem, dass zu viele Funktionen weggelassen werden. 
Wenn die Funktionen recht kurz sind, werden sie auch weggelassen, obwohl 
sie aufgerufen werden. Durch ein wenig "herumprobieren" konnte ich ein 
kleines Beispiel finden, bei dem mein Problem auch auftritt. (Das 
Beispiel soll nur den Fehler beschreiben und stellt kein sinnvolles 
Programm dar.) Ich habe vier Testfunktionen test1 bis test4, welche ich 
alle in der main-Funktion aufrufe. Dabei werden die ersten zwei 
Funktionen weggelassen.
1
int main(void)
2
{
3
   test1();
4
   test2();
5
   test3();
6
   test4();
7
   while(1);
8
}
9

10
void test1(void)
11
{
12
   PORTB = 0U;
13
   PORTB += 1U;
14
}
15

16
void test2(void)
17
{
18
   PORTB = 0U;
19
   PORTB += 1U;
20
   PORTB += 1U;
21
}
22

23
void test3(void)
24
{
25
   PORTB = 0U;
26
   PORTB += 1U;
27
   PORTB += 1U;
28
   PORTB += 1U;
29
}
30

31
void test4(void)
32
{
33
   PORTB = 0U;
34
   PORTB += 1U;
35
   PORTB += 1U;
36
   PORTB += 1U;
37
   PORTB += 1U;
38
}

(Wenn ich den Inhalt der Funktionen austausche, so werden immer die 
Funktionen weggelassen, welche drei oder weniger Zeilen Operationen 
beinhalten.)

Über den Parameter "-Wl,--print-gc-sections" lass ich mir ausgeben, 
welche Sections weggelassen werden und erhalte folgende Ausgabe:
1
...
2
c:/winavr/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: Removing unused section '.text.test1' in file './trunk/FR_CONTROL.o'
3
c:/winavr/bin/../lib/gcc/avr/4.3.3/../../../../avr/bin/ld.exe: Removing unused section '.text.test2' in file './trunk/FR_CONTROL.o'
4
...

Im Map-File ist für diese beiden Funktionen auch kein Speicherbereich 
zugewiesen.

Den Hinweis zu Startup-Codes und Interrupt-Vektoren hatte ich gelesen. 
Aber dies ist ja etwas anders.

Hat jemand eine Idee, was ich falsch mache?
Gruß
Ben
Gast #3364399
Lesenswert?

Hallo,

die Eigenschaft, nicht benötigte Funktionen nicht zu linken, war zu 
Urzeiten mal völlig selbstverständlich, ich erinnere mich an 
verschiedene Z80-Linker, die das überhaupt oder mit dem Parameter /s 
(scan) beherrscht haben. Wenn ich das Modul für Fliesskommaarithemtik /s 
aufgerufen habe und keine Division im Programm vorkam, wurde der Code 
für die Division auch nicht gelinkt. Das ist irgendwann dem heutigen 
Paradigma zum Opfer gefallen, dass das Einsparen von Speicherplatz dumm 
und rückständig ist, man wird ja in vielen Foren massiv angefeindet wenn 
man den Speicherbedarf überhaupt erwähnt.

Ich habe allerdings nie begriffen, was denn der Vorteil sein soll, nie 
benutzte Codestücke mit einzubauen. Nur der Linker wird dadurch 
zugegebenermassen einfacher.

Nicht jede Entwicklung ist ein Fortschritt.

Gruss Reinhard

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren