Forum: Compiler & IDEs Effektive Speichernutzung


von Der T. (Gast)


Lesenswert?

Hallo!

Controller: ATMEGA128
Umgebung: WinAVR

Ich schreibe hier das Programm für einen Prüfplatz mit 85
Prüfschritten.
Dazu muß ich u.a. 136 Relais und 210 LED's ansteuern. Dies geschieht
logischerweise seriell mittels mehreren Allegro A6818.

Ich habe nun eine Funktion geschrieben, die die Daten ausgibt. Die
daten liegen in einem 20Byte un einem 28Byte "Char-Array". Deses
Array habe ich mittels "volatile unsigned char def_led[28]" und
"unsigned char def_relay[20]" definiert.

Bisher alles ok! :)

Nun das Problem:
Wenn ich nun 85 Prüf-Funktionen anlege und jede davon greift auf das
mit volatile definierte Char zu, so benötigt der Compiler alleine
hierfür 85* (20+28) Byte -> 4080Byte RAM zum verwalten! :(

Wie könnte ich dies eleganter lösen?

Ich hoffe, ich habe mich verständlich ausgedrückt..

Im Vorraus schonmal einen herzlichen Dank!

von Stromspannung (Gast)


Lesenswert?

Hi,

ohne Kenntnis der in diesen Arrays kann man nicht sagen, dass man diese
Ersetzen kann. Würde es einen einfachen Algoritmus geben, hättest du ihn
sicherlich verwendet :)
Oder benutzt hier jede der 85 Prüfroutinen das gleiche/selbe Feld? Dann
ist eine Vervielfachung natürlich Quatsch. Kann man das Feld nicht,
sagen wir mal global machen? Warum eigentlich volatile? Ich verstehe
das so, dass aus diesem Array nur Werte zur Ausgabe geholt werden, dann
ändern sich diese Felder doch aber nicht?

von Der T. (Gast)


Lesenswert?

Hallo Stromspannung!

Im Prinzip ist das Array nur die Vorlange für das auszugebende
Bitmuster. Da sowohl das Hauptprogramm, als auch die einzelnen
prüffunktionen aud die Relais und die LEDs zugreifen können müssen,
habe ich die Variablen mit volatile definiert.

Um das ändern der Zustände schön übersichtlich zu machen, habe ich eine
Header-Datei erstellt, wo alle Aktionen per defines vorgegeben sind.
z.B.
#define RELAY_K100_ON   def_relay[10] |= 0x10
#define RELAY_K100_OFF  def_relay[10] &= ~0x10
usw..

Nachdem ich dann die Zusände wie gewünscht angepasst habe, schiebe ich
die daten mittels einer Funktion "Send_RELAY_data();" raus.

Verstehst du, was ich meine?

Gruß,
Techniker

von Alex (Gast)


Lesenswert?

volatile braucht man nur, wenn Variableninhalte ausserhalb des normalen
Programmablaufs (also in Interrupts) geändert werden könnten.

von Der T. (Gast)


Lesenswert?

Hmm..
D.h. wenn eine normale Funktion die Variable ändert, bekommt das die
Hauptfunktion mit und umgekehrt? :)

Braucht man volatile wirklich nur in Verbindung mit Interrupts?

von Karl heinz B. (kbucheg)


Lesenswert?

> Nun das Problem:
> Wenn ich nun 85 Prüf-Funktionen anlege und jede davon greift auf
> das mit volatile definierte Char zu, so benötigt der Compiler
> alleine hierfür 85* (20+28) Byte -> 4080Byte RAM zum verwalten! :(

?
Was hast du denn fuer eine perverse Rechnerei.
Die Arrays sind doch wohl global, existieren also
nur ein einziges Mal, bzw. sie existieren in der main()

> Hmm..
> D.h. wenn eine normale Funktion die Variable ändert, bekommt
> das die Hauptfunktion mit und umgekehrt? :)

Wie wäre es mit einem C-Buch?
Sieht aus als ob du das nötig hättest.

Das Verständnis von 'Argument Passing' bzw. den 'Scope-Regeln'
ist eigentlich Grundvoraussetzung für professionelle Software-
Entwicklung (selbst wenn man sie nur im Hobby Bereich betreibt).

von Der T. (Gast)


Lesenswert?

@Karl:

Die Rechnerei ist nicht pervers, sondern genau dass, was mir WinAVR
Ausgibt!

Klammere ich nämlich jegliche Zugriffe auf das Array aus einer
Prüffunktion aus und kompiliere das Programm neu, so zeigt mir gcc
genau 48Byte weniger RAM-Verbrauch. Wenn das nicht irgendein Zufall
ist...

Und funktionieren mein bisheriges Speichermodell gut, da ich es mit 3
prüfschritten getestet habe. Nur für das komplette Projekt reichen mir
so die 4kB nicht.

Was ich möchte ist genau das, was du schilderst, nämlich EINMAL 20Byte
bzw. 28Byte Array und dies Global. Was ich bei meinem problem eben
nicht verstehe, warum GCC bei jeder Unterfunktion genau diese Größe
nocheinmal braucht?

Und noch eine Bitte: Bevor du solche Beiträge verteilst, wie "perverse
Rechnerei" und "Wie wäre es mit einem C-Buch?" gibt doch konstruktive
Beispiele bzw. Hilfe oder lass es komplett bleiben! - Danke!

Schöne Grüße!

von Karl heinz B. (kbucheg)


Lesenswert?

Zeig mal dein Program.
Irgendwas hast du da gaenzlich daneben programmiert
oder ich versteh noch nicht, bzw. hab noch nicht richtig
erraten wie dein Pgm-Aufbau ist.

> konstruktive
> Beispiele bzw. Hilfe oder lass es komplett bleiben! - Danke!
Ich denke ich hab schon mehr als einmal bewiesen, dass ich
sehr wohl konstruktiv arbeiten kann und das nicht mal
so schlecht.
Hingegen hast du in diesem Beitrag bewiesen, dass du immer
noch nicht gelernt hast, dass man wenn man ein Problem in
einem Programm hat, man dieses Problem immer mit realem
Code illustriert.

von Dirk (Gast)


Lesenswert?

Hi,

aendern sich die Daten im Array? wenn nicht einfach in das flash
legen.

Gruß,
Dirk

von Der T. (Gast)


Lesenswert?

@Ich kenn dich nicht persönlich und kenn (jedenfalls bewusst) auch
keinen anderen konstruktiven beitrag von Dir. Ich habe nur deinen
Beitrag hier gelesen und dazu passend geantwortet. Aber nix für ungut..
;)

Den kompletten Code zu Posten wäre ein bischen viel.

Ich poste hier mal die relevanten Stellen für LED-Ansteuerung:


main.h:
1
unsigned char def_led[28]; //Puffer für LED-Status


A6818.c
1
//########################################################################
2
// LED-Daten ausgeben
3
//########################################################################
4
void A6818_LED_set ( unsigned char *data )
5
{
6
 unsigned char i, n;
7
 
8
 for (n=28; n>0; n--) //28 Durchläufe mit je 8Bit => 224Bits
9
 {
10
  for (i=0; i<8; i++)
11
  {
12
   if ( *(data+n-1) & 1<<(7-i) )
13
   {
14
    A6818_LED_SDI_HIGH;
15
    Delay1us(25);
16
  A6818_LED_CLK_LOW;
17
    Delay1us(25);
18
    A6818_LED_CLK_HIGH;
19
    Delay1us(25);
20
   }
21
   else
22
   {
23
    A6818_LED_SDI_LOW;
24
    Delay1us(25);
25
  A6818_LED_CLK_LOW;
26
    Delay1us(25);
27
   A6818_LED_CLK_HIGH;
28
    Delay1us(25);
29
   }
30
  }
31
 }
32
 A6818_LED_STR_HIGH;
33
 Delay1us(25);
34
 A6818_LED_STR_LOW;
35
}


def_led.h:
1
#define LED_D001_OFF  def_led[0] &= ~0x03
2
#define LED_D001_GN  def_led[0] &= ~0x03; def_led[0] |= 0x01
3
#define LED_D001_RT  def_led[0] &= ~0x03; def_led[0] |= 0x02
4
5
#define LED_D002_OFF  def_led[0] &= ~0x0c
6
#define LED_D002_GN  def_led[0] &= ~0x0c; def_led[0] |= 0x04
7
#define LED_D002_RT  def_led[0] &= ~0x0c; def_led[0] |= 0x08
8
9
(usw..)


Nun rufe ich hald in einer ganz normalen Funktion z.B.
1
LED_D001_RT;
2
A6818_LED_set(def_led);
auf - sonst nix!

Und mit jeder zusätzlichen Funktion steigert sich reproduzierbar der
RAM-Verbrauch um genau 48Byte (20Byte für Relais, 28Byte für die LEDs)

Gruß,
Techniker

von Der T. (Gast)


Lesenswert?

@Dirk:
An diese Notlösung hätte ich auch schon gedacht. - Danke!

Aber ich kann mir nicht vorstellen, dass es mit Arrays nicht gehen
sollte.. :-/

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Anstelle von

main.h:
1
unsigned char def_led[28]; //Puffer für LED-Status

solltest Du
1
extern unsigned char def_led[28]; //Puffer für LED-Status

schreiben und den Speicher in exakt einem Source-File definieren

Bei Deiner Schreibweise wird der Speicher bei jedem Einbinden von
main.h erneut definiert (und nicht nur deklariert), was eigentlich auch
zu einer Linkerfehlermeldung führen sollte.

von Fabian Scheler (Gast)


Lesenswert?

Hallo,

also wenn ich das richtig sehe, reservierst du in einem Header (main.h)
Speicher, so etwas tut man nicht, dieser Speicher wird nämlich jedes Mal
reserviert, wenn du den Header irgendwo einbindest, zusätzlich wird
jedes Mal ein Symbol erzeugt, der Linker müsste dir also auf die Füße
treten und dir sagen, dass da ein Symbol mehrfach definiert ist.
Zu Lösung des Problems:

main.h
1
extern unsigned char def_led[28];

main.c
1
unsigned char def_led[28];

ein Header legt nur die Schnittstelle fest, alles was später irgendwie
zu einem Symbol werden könnte, hat in einem Header nichts verloren!

Ciao, Fabian

von Der T. (Gast)


Lesenswert?

@Fabian:

Danke für deinen Tipp!

Habs jetzt so gemacht, wie du es geschrieben hast. Lässt sich ohne
Fehler kompilieren und funktioniert auch. Nur am RAM-Verbrauch ändert
sich garnix.. :(

von Karl heinz B. (kbucheg)


Lesenswert?

> jedes Mal ein Symbol erzeugt, der Linker müsste dir also auf die
> Füße treten und dir sagen, dass da ein Symbol mehrfach definiert
> ist

Hat nicht der gcc-Linker eine Erweiterung, die genau dieses
verhindert. Ich kann mich dunkel erinnern, dass der automatisch
mehrfach-Definitionen zu einer zusammen fasst.

@Techniker
Mit RAM: meinst du da SRAM oder Flash?

Bei SRAM: das kann nicht sein. Das Array existiert
jetzt (mit der extern Erweiterung) mit Sicherheit nur
ein einziges mal. Da muss noch was anderes sein.

von Stefan (Gast)


Lesenswert?

"Da muss noch was anderes sein."

Sehe ich auch so. Aber das kann man ja zum Glück im Memory-Map-File und
im Listing-File nachsehen.

von Der T. (Gast)


Lesenswert?

@Stefan:

Hab mir beide Files angeschaut, kann damit aber nicht wirklich was
anfangen.. ;)

Welcher bereicht ist denn im MAP-File interessant, dann poste ich den
mal.

Gruß,
Techniker

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe deinen Beispielcode soweit nachgestellt, bis er kompiliert
werden kann. Und dabei die Maßnahmen der anderen Antworten
berücksichtigt.

Zum Kompilieren wurde die Toolchain WinAVR 4.1.0 verwendet. Natürlich
kommt kein lauffähiges Programm heraus, aber darum geht es ja nicht.

Bei einer oder drei "LED-Funktionen" kommt kein erhöhter
Speicherbedarf zustande. Es werden immer 28 Bytes im BSS Bereich
angelegt (s. Ausgabe beim Make) und exakt ein Symbol def_led (s.
main.sym)

Allerdings habe ich einige Makros nur als Dummy drin, weil du dafür
nichts angegeben hast. Es kann mit geringer Wahrscheinlichkeit sein,
dass in den Makros Speicher angelegt wird

Ich würde vorschlagen, dass du dieses Projekt soweit in Richtung deines
Codes abänderst, bis der Fehler reproduzierbar ist.

von Der T. (Gast)


Lesenswert?

@Stefan:

Danke, werde ich heute Nachmittag mal ausprobieren.

Nochwas: Warum ist in der main.c nicht die main.h include'd?
Ist das bei WinAVR 4.1.0 nicht mehr nötig? (arbeite noch mit 3.4.3)

Gruß,
Techniker

von Stefan (Gast)


Lesenswert?

Bei diesem Projekt ist es egal, ob dir main.h in main.c included wird
oder nicht.

Ich habe es rausgelassen, weil darin nur das externe  Array def_led
bekannt gemacht wird und main.c dieses Symbol schon kennt.

von Der T. (Gast)


Lesenswert?

Hallo Stefan!

Leider hat dein Code-Vorschlag auch nicht wirklich was gebracht.. :(

Hier mal 2 Ausschnitte des MAP-Files, welche evtl. Interessant sein
könnetn. Kannst du daraus was erkennen?

-----------------------

Allocating common symbols
Common symbol       size              file

Pruefung            0x1               main.o
clock_posy          0x1               main.o
GS_blink            0x2               main.o
def_relay           0x14              main.o
DIG_value           0x2               main.o
xcursor             0x1               draw.o
font                0x2               fontsoft.o
LCD_BUSY            0x1               main.o
__brkval            0x2
C:/Programme/WinAVR/bin/../lib/gcc/avr/3.4.3/../../../../avr/lib/avr5\li 
bc.a(malloc.o)
def_led             0x1c              main.o
clock_pic           0x1               main.o
Mess_cnt            0x4               main.o
pr                  0x1               main.o
Pruefhelp_2         0x1               main.o
fontheight          0x1               fontsoft.o
ycursor             0x1               draw.o
clock_cnt           0x2               main.o
clock_posx          0x1               main.o
Pruefstatus         0x9               main.o
sw                  0x1               main.o
buzzerbeepcount     0x2               main.o
lk                  0x1               main.o
__flp               0x2
C:/Programme/WinAVR/bin/../lib/gcc/avr/3.4.3/../../../../avr/lib/avr5\li 
bc.a(malloc.o)
fontwidth           0x1               fontsoft.o
Pruefhelp_1         0x1               main.o

Memory Configuration

Name             Origin             Length             Attributes
text             0x00000000         0x00020000         xr
data             0x00800060         0x0000ffa0         rw !x
eeprom           0x00810000         0x00010000         rw !x
default        0x00000000         0xffffffff

-----------------------

.data           0x00800100      0xdfa load address 0x00013796
                0x00800100                PROVIDE (__data_start, .)
 *(.data)
 .data          0x00800100      0x235 main.o
 .data          0x00800335      0xbbe pruefschritte.o
 .data          0x00800ef3        0x6
C:/Programme/WinAVR/bin/../lib/gcc/avr/3.4.3/../../../../avr/lib/avr5\li 
bc.a(malloc.o)
                0x00800ef5                __malloc_heap_start
                0x00800ef3                __malloc_heap_end
                0x00800ef7                __malloc_margin
 *(.gnu.linkonce.d*)
                0x00800efa                . = ALIGN (0x2)
 fill         0x00800ef9        0x1 00
                0x00800efa                _edata = .
                0x00800efa                PROVIDE (__data_end, .)

.bss            0x00800efa       0x63
                0x00800efa                PROVIDE (__bss_start, .)
 *(.bss)
 .bss           0x00800efa        0xa main.o
 *(COMMON)
 COMMON         0x00800f04       0x4f main.o
                                  0x0 (size before relaxing)
                0x00800f04                Pruefung
                0x00800f05                clock_posy
                0x00800f06                GS_blink
                0x00800f08                def_relay
                0x00800f1c                DIG_value
                0x00800f1e                LCD_BUSY
                0x00800f1f                def_led
                0x00800f3b                clock_pic
                0x00800f3c                Mess_cnt
                0x00800f40                pr
                0x00800f41                Pruefhelp_2
                0x00800f42                clock_cnt
                0x00800f44                clock_posx
                0x00800f45                Pruefstatus
                0x00800f4e                sw
                0x00800f4f                buzzerbeepcount
                0x00800f51                lk
                0x00800f52                Pruefhelp_1
 COMMON         0x00800f53        0x2 draw.o
                                  0x0 (size before relaxing)
                0x00800f53                xcursor
                0x00800f54                ycursor
 COMMON         0x00800f55        0x4 fontsoft.o
                                  0x0 (size before relaxing)
                0x00800f55                font
                0x00800f57                fontheight
                0x00800f58                fontwidth
 COMMON         0x00800f59        0x4
C:/Programme/WinAVR/bin/../lib/gcc/avr/3.4.3/../../../../avr/lib/avr5\li 
bc.a(malloc.o)
                                  0x0 (size before relaxing)
                0x00800f59                __brkval
                0x00800f5b                __flp
                0x00800f5d                PROVIDE (__bss_end, .)
                0x00013796                __data_load_start = LOADADDR
(.data)
                0x00014590                __data_load_end =
(__data_load_start + SIZEOF (.data))

.noinit         0x00800f5d        0x0
                0x00800f5d                PROVIDE (__noinit_start, .)
 *(.noinit*)
                0x00800f5d                PROVIDE (__noinit_end, .)
                0x00800f5d                _end = .
                0x00800f5d                PROVIDE (__heap_start, .)

.eeprom         0x00810000        0x0
 *(.eeprom*)
                0x00810000                __eeprom_end = .

von Stefan (Gast)


Lesenswert?

Was hat er nicht gebracht?

Das Array def_led in deinem Programm ist exakt 0x1c = 28 Bytes gross.
Es ist genauso wie in meinem Code nicht der Übeltäter.

Fetten DATA Speicher belegt pruefschritte.o. Dort würde ich die Suche
beginnen. Leider sind keine Symbole von diesem File erkennbar.
Möglicherweise handelt es sich um initialisierte static Variablen.

von Der T. (Gast)


Lesenswert?

Hallo Stefan!

O-Dateien kann man nicht leserlich öffen, oder? ;)

Als Static ist darin auch nix definiert. Kann ich irgendwie rausfinden,
wer da soviel Speicher frisst?

In der Datei sind hald die ganzen Prüfschriit-Funktionen, die jede auf
die beiden Arrays zugreifen. Kommentiere ich in einer Funktion die
Aufrufe, welche mit den Arrays arbeiten aus, so verkleinert sich der
RAM-Verbrauch um jeweils 48Byte..?!? :-o

Irgendwas läuft da extrem schief.. :-/

Sowas hatte ich bisher auch noch nicht! Und dazu funktioniert
komischerweise auch alles bestens! (Nur der RAM geht mir hald aus..)

von Stefan (Gast)


Lesenswert?

Ja, dann mach doch endlich mal Butter bei die Fische und zeige, was eine
typ. Prüfroutine macht oder checke das selbst ab, wenn du den Code nicht
öffentlich zeigen willst.

Das Beispiel, dass du bisher gegeben hast, zeigt das Verhalten nicht,
ist allerdings auch nicht vollständig siehe meine Dummy-Defines. Daher
auch mein Vorschlag nach und nach, deinen Code in mein
unproblematisches Beispiel einzubauen.

Für mich bleibt nach allem der Schluss, dass die echten Defines einen
Murks bauen.

von Stefan (Gast)


Lesenswert?

Nachtrag:

Du kannst *.o Dateien selbstverständlich disassemblieren. Ich glaube
OBJDUMP aus der GNU Toolchain macht das. Das ist allerdings in deinem
Stadium ziemlich heavy, es ist wesentlich einfacher den C-Quellcode zu
lesen.

von -Daniel- (Gast)


Lesenswert?

@ der wahre

zuerst vorab, Karl kenne ich von der deutschen NG
und er hilft gerne weiter, vorausgesetzt das Problem
ist klar geschildert. Da dieses "problemschildern"
schwer ist (mir auch manchmal), so ist ab besten
den Code mitangeben (zuerst sinnvoll reduzieren)

und jetzt zu Fragen
nie Variablen in .h Datei deklarieren
wenn diese in zig .c Datien includiert wird, so wird
in jeder .o Datei Speicher dafür angelegt(oder vorgesehen).

extern char feld[];

zweitens, volatile braucht man, wenn man verhindern möchte
dass der Variablewert aus dem (CPU lokalem)Cache benutzt wird ..
gleichzeitig wo asnychron (zB aus Interrupt oder von anderer CPU)
die Variable im eigentlichem Variablen RAM verändert wurde.

wenn du dein Problem debuggen willst, so schaue dir
nm und "objdump -d" an

ansonsten kann ich mir nicht vorstellen, dass der Zugriff
alleine zur Speicherduplikation führen soll

Gruss, Daniel

von Fabian Scheler (Gast)


Lesenswert?

@kbucheg:

> Hat nicht der gcc-Linker eine Erweiterung, die genau dieses
> verhindert. Ich kann mich dunkel erinnern, dass der automatisch
> mehrfach-Definitionen zu einer zusammen fasst.

das macht der Linker aber nur für sog. weak-Symbole - solche Symbole
erzeugt der Compiler, wenn er C++-Templates instantiiert, für normale
Symbole gilt dies nicht, wenn das so wäre - auweia, in 2 Modulen wird
versehentlich dieeselbe globale Variable deklariert, welche Version
verwendet man den nun gerade => das muss einen Fehler geben

Ciao, Fabian

von Patrick D. (oldbug) Benutzerseite


Lesenswert?

Nö, das macht der gcc ganz automatisch.

Beispiel?
Bittesehr:

main.c
1
int testvar;
2
3
int
4
main(void)
5
{
6
        return 0;
7
}

badguy.c
1
int testvar;
2
3
void
4
dummy(void)
5
{
6
        return;
7
}

Compiler-Lauf:
gcc -O -g -Wl,-Map=test.map,--cref -o test.exe main.c badguy.c

Mapfile Auszug:
Allocating common symbols
Common symbol       size              file
[..]
testvar             0x10              Temp/ccURaaaa.o
[..]

 COMMON         0x00404060       0x10 Temp/ccURaaaa.o
                0x00404060                testvar

testvar                               Temp/ccMdbaaa.o
                                      Temp/ccURaaaa.o

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ich halte das für einen philosophischen Fehler im Compiler. Dadurch wird
schlampiger und schlechter Programmierstil unterstützt und die diversen
Anfänger kapieren nie, was der Unterschied zwischen Deklaration und
Definition von Variablen ist.

Aber philosophische Diskussionen sind müßig - genauso wie die über die
auf Windows-Systemen fehlerhafte (sprich: nicht zulässige)
Unterscheidung zwischen Groß- und Kleinschreibung von Dateinamen durch
make oder ähnliche Tools.

von Fabian Scheler (Gast)


Lesenswert?

@OldBug,kbucheg:

sapperlot, das hätte ich jetzt nicht gedacht, vielleicht bin ich dafür
einfach zu gut erzogen ... ;-)

@Rufus:

da hast du wohl leider recht

von -daniel- (Gast)


Lesenswert?

@ Fabian Scheler

die weak Symbole sind mir schon früher begegnet
ich hab grob (ganz grog) kapiert was sie bewirken
Du scheinst Dich mehr damit beschäftigt zu haben
Hast du paar Geheimquellen die Du vielleicht als Link
angeben könntest?
nm ist mir viel zu knapp in der Beschreibung
ausserdem fehlen da jegliche Beispiele (für Programmierer)
Wäre super nett.

Gruss, Daniel

von Fabian Scheler (Gast)


Lesenswert?

@-daniel-:

sorry, aber einen besseren Link als die nm-manpage bzw. die gcc und ld
info-Page kann ich dir leider auch nicht geben. In der gcc info-Page
findet man gewissermaßen noch einen Verwendungshinweis: das
weak-Attribut kann verwendet werden, wenn der Benutzer
Bibliotheksfunktionen überschreiben können soll, vielleicht erhellt das
den Sachverhalt etwas?

Wo wünscht du dir in der nm-manpage noch mehr Info? Vielleicht kann ich
ja eine gezielte Frage beantworten?

Ciao, Fabian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Ja, weak ist dafür da, um bestimmte Symbole in einer Bibliothek
vorgeben zu können, sie dennoch vom Nutzer überschreibbar zu halten.
Ein typischer Fall dafür bei der avr-libc ist die Interrupt-Vektor-
Tabelle: der Startup-Code definiert eine vollständige Tabelle, in der
als Ziele __vector_1 ... __vector_N definiert sind und mittels .weak
jeweils auf das Symbol __bad_interrupt gemappt werden.

Wenn nun ein Nutzer seinen eigenen Vektor einbinden will, definiert er
selbst das Symbol __vector_M.  Da das in der Bibliothek als "weak"
markiert ist, gibt es keinen Linkerfehler über eine doppelte
Symboldefinition, die es ohne .weak geben würde.

***

Das Überlagern der Common-Blöcke ist übrigens ausdrücklich im
C-Standard als eine der Möglichkeiten zur Behandlung globaler
Variablen genannt (wenn ich mich recht entsinne, wird es als das
ursprünglich von K&R implementierte Konzept beschrieben).  Wenn man es
im GCC abschalten will, kann man das mit -fno-common tun.

von Der T. (Gast)


Lesenswert?

Wollt bloß schnell berichten, dass ich nun den Code nach Stefan's
Hinweise umgeschrieben habe und nun ist der Fehler weg! :-D

-> Speicherverbrauch (RAM) unter 5%! ;)
(Flash ist zu 78% ausgelastst)

(Wobei mich immer noch interessieren würde, was es genau war.. :-/ )

Vielen Dank an alle! :)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.