malloc / realloc- Probleme
-
pale dog schrieb:
btw: wenn sich malloc aufhängt, hast du wahrscheinlich ein paar strukturen auf dem heap zerstört (über den speicher hinausgeschrieben oder sowas).
musste wohl alle codes überprüfen, die mit heap-memory arbeiten.was für 'nen heap benutzt du?
Gut, das mit dem realloc habe ich behoben, alleine geändert hat's nichts
.
Ich bin wie Du der Meinung, daß ich mir irgendwie den Heap zersäble, komm'aber nicht wirklich drauf, wie.Ein Verdacht entspinnt sich um die Interrupts:
Ich mache es oft so, daß ich Daten für Interruptroutinen auf den Heap kippe, damit die sie beim Aufruf wegarbeiten. malloc, calloc, realloc und free sind doch angeblich reentrant.
Ich weiß, daß es zwangsläufig passieren wird, daß ein malloc mal bei der Arbeit unterbrochenund dann irgendeine Interruptroutine einen free auf ihre Jobdaten setzen wird.
Eigentlich dürfte doch da nichts Böses herrühren, geschützt habe ich immer nur Anlagen komplexerer Jobdaten, wenn z.B. mehrere Elemente zusammengehören und technisch nicht in einem einzigen malloc angelegt werden konnten.
Jedenfalls hatte ich daher noch nie Negativerlebnisse, aber vielleicht hat mich auch nur der Zufall geschützt
-
proggingmania schrieb:
alterpointer = realloc(alterpointer, size_t);
ist bedenkenlos, dafür ist doch realloc da.nö, wenn 'realloc' 0 zurückgibt, ist dein pointer futsch. das ist nicht im sinne des erfinders...
pointercrash() schrieb:
Ein Verdacht entspinnt sich um die Interrupts:
Ich mache es oft so, daß ich Daten für Interruptroutinen auf den Heap kippe, damit die sie beim Aufruf wegarbeiten. malloc, calloc, realloc und free sind doch angeblich reentrant.das kann man so pauschal nicht sagen. schau dir mal den quelltext deiner heap-implementation an, ob's so ist.
pointercrash() schrieb:
Ich weiß, daß es zwangsläufig passieren wird, daß ein malloc mal bei der Arbeit unterbrochen
und dann irgendeine Interruptroutine einen free auf ihre Jobdaten setzen wird.
dann versuch doch mal sowas ähnliches:
void *safe_malloc (bool called_from_isr_or_interrupts_already_disabled, size_t size) { volatile void *p; if (!called_from_isr_or_interrupts_already_disabled) disable_interrupts(); p = malloc(size); if (!called_from_isr_or_interrupts_already_disabled) enable_interrupts(); return p; }
selbiges mit free, realloc, etc. und dann alle aufrufe in deinem code dagegen tauschen, vielleicht hilfts...
-
pale dog schrieb:
das kann man so pauschal nicht sagen. schau dir mal den quelltext deiner heap-implementation an, ob's so ist.
Schwierig, ist eine precompiled Lib, aus der kriege ich nicht mehr heraus als den tracebaren Assemblercode ...
pale dog schrieb:
dann versuch doch mal sowas ähnliches:
void *safe_malloc (bool called_from_isr_or_interrupts_already_disabled, size_t // usw ...
selbiges mit free, realloc, etc. und dann alle aufrufe in deinem code dagegen tauschen, vielleicht hilfts...
Ja, hätte helfen können, spätestens bei free() kriege ich Schwierigkeiten, weil ich nach obig beschriebenem Schema vorzeitige Interrupt- Freigaben provoziere = Interruptkaskadierung, hab' noch mit Flags experimentiert, ist auf die Nase gefallen ...
Ich hab's aber über diesen Fehler zwischenzeitlich gefunden:
Mein Stackviewer weiß alles über im normalen Programmlauf aufzufindende Funktionen und deren Speicherverbrauch, beim Interrupt traced er nur eine Aufruftiefe. War zwar eigentlich großzügig dimensioniert, aber der Interruptstack scheint in den Heap übgergelaufen zu sein und hat der Heapverwaltung die Beine weggeknüppelt.
Ich werde morgen nochmal nachtesten, ob sich damit das Kuriosum des unerwarteten Speicherverbrauchs bei der realloc- Loop erklären läßt
, die resultierende Frage lautet, nach welcher Strategie malloc() & Co arbeiten? Gibt es da nicht doch Allgemeineres?
Jedenfalls piept mein Piepser nun ohne Absturz
, für heute ist's genug.
Danke!
-
mal ganz davon abgesehen, in einer interrupt-routine malloc(), free(), etc. aufzurufen ist sowieso nicht toll. besser die isr hat statischen speicher, den sie benutzen kann...
-
pale dog schrieb:
mal ganz davon abgesehen, in einer interrupt-routine malloc(), free(), etc. aufzurufen ist sowieso nicht toll. besser die isr hat statischen speicher, den sie benutzen kann...
... jaja, und dann eine Art Ringbuffer- Verwaltung drüberklatschen, kenne das schon. Nur statischer Speicher ist dann auch statisch weg. Wenn man ein OS drunterliegen hat, das virtuell Speicher ohne Ende beschaffen kann, eine probate Methode. Wenn Du einen nackten Controller mit 16 k RAM hast, wo sich die C- Runtime bereits zur Selbstverwaltung knapp 2 kB gönnt, ist es oft einfach zu eng, allen ISRs für alle Eventualitäten
genug Speicher zu gönnen.
Im Gegenteil, es ist sogar einfacher, Engpässe zu finden, wenn Dir die Runtime von sich aus erzählt, wo sie mit dem Speicherbeschaffen gescheitert ist.Wie gesagt, Daten für ISRs in Befehlslisten auf dem Heap per malloc() abzulegen, die ISRs arbeiten das bei Aufruf ab und geben den Speicher mit free() zurück, hat eigentlich immer gut geklappt
. Einziges Manko: Die Dinger brauchen dammich viel Rechenzeit
, die noch nichtmal garantiert ist (58 ... 102 Cycles) was einer ISR nicht immer gut steht
, da geht's am statischen Speicher nicht vorbei ...
Ich war mir nur nicht ganz sicher, ob Reentranz von malloc() & Co nicht nur eine notwendige, sondern auch hinreichende Bedingung darstellen ...
-
pointercrash() schrieb:
Im Gegenteil, es ist sogar einfacher, Engpässe zu finden, wenn Dir die Runtime von sich aus erzählt, wo sie mit dem Speicherbeschaffen gescheitert ist.
naja, aber was machst du wenn malloc/realloc mal schief gehen?
hängt sich das ding dann auf oder resettet es sich?pointercrash() schrieb:
Einziges Manko: Die Dinger brauchen dammich viel Rechenzeit
, die noch nichtmal garantiert ist (58 ... 102 Cycles) was einer ISR nicht immer gut steht
auch deshalb würde ich lieber die finger davon lassen.
btw: oft ist der einsatz von malloc o.ä. bei kleinen embedded systemen unvorteilhaft und eine speicherverschwendung dazu. damit es einigermassen zuverlässig läuft (etwa wegen fragmentierung), muss man dem heap grosszügig speicher verpassen d.h. 10% oder so liegen immer brach...
--> http://www.embedded.com/2000/0004/0004feat2.htm
-
pale dog schrieb:
naja, aber was machst du wenn malloc/realloc mal schief gehen?
hängt sich das ding dann auf oder resettet es sich?Solange ich im BDM debuggen kann, sehe ich ja, wo's knallt
. Peinlich wird's, wenn's erst im Feld passiert
... oder der Debugger gleich mit absäuft
. Üblicherweise verzweige ich auf eine Routine, die die Hardware erstmal gesichert abschaltet. Hat das Ding ein Display, kann man anzeigen, wo's hängt. Besser: Einen unkritischen Pin als TX einer async serial verwenden und den Returnstack darüber ausgeben. Naja, und beten, daß das Ding wirklich noch soviel tut ...
pale dog schrieb:
pointercrash() schrieb:
Einziges Manko: Die Dinger brauchen dammich viel Rechenzeit
, die noch nichtmal garantiert ist (58 ... 102 Cycles) was einer ISR nicht immer gut steht
auch deshalb würde ich lieber die finger davon lassen.
Prinzipiell ja, das ist ja das diametrale Dilemma zwischen Laufzeit- und Speicherverbrauchsoptimierung.
Sagen wir's mal so: Applikationsbezogen juckt es momentan nicht, da die laufzeitkritischen Teile noch gewaltig Luft haben und sich die CPU momentan eher langweilt. Da siegt meine persönliche Faulheit.pale dog schrieb:
btw: oft ist der einsatz von malloc o.ä. bei kleinen embedded systemen unvorteilhaft und eine speicherverschwendung dazu. damit es einigermassen zuverlässig läuft (etwa wegen fragmentierung), muss man dem heap grosszügig speicher verpassen d.h. 10% oder so liegen immer brach...
Interessanter Artikel, aber wenn Du aufwendige MMIs ins System schleifen mußt, weil Dein Kunde das System geschwätziger haben will, mehrsprachig und die Dudeltöne selbst konfigurieren will, rutscht auf einmal viel mehr Zeug durchs System.
Den Vorgänger habe ich vor 11 Jahren in 1800 Byte Assembler programmiert, der Nachfolger hat vollständig über Systemmenü konfigurierbare Hardware (jumperless) und kann englisch, holländisch, deutsch, bedarfsweise die Marseillaise dudeln und braucht momentan fast 38 kB ROM :p .
Die 256 Byte RAM von damals langen dem C- Compilat noch nichtmal zum Startup.
Nicht, daß der Endbenutzer etwas davon hätte, aber wenn mir auf dem Controller der Platz ausgeht, nehm' ich einfach schneller & größer, pinkompatibel. Ein funktionierendes Konzept zu kippen, wäre teurer. Man darf halt nicht vergessen, welche Schwächen man sich durch den Gebrauch einhandelt.
Die 10% Brache kannste vergessen, ich schätze, bei "first fit", nachdem mein malloc() zu arbeiten scheint, produziert gerade 30% Brache, durch Umstellung bei der Initialisierung kann ich das vielleicht drücken, wenn nicht, werde ich sehen, wie knapp es wird.
Eigentlich vermisse ich an C das Fehlen einer Anweisung, die eine "garbage collection" durchführt.
-
pointercrash() schrieb:
Solange ich im BDM debuggen kann, sehe ich ja, wo's knallt ;).
oh, BDM? benutzt du einen freescale?
pointercrash() schrieb:
Peinlich wird's, wenn's erst im Feld passiert
das ist nicht peinlich, das ist absolut fatal.
mikroprozessorschaltungen dürfen vielleicht versagen, wenn die hütte abbrennt oder wenn al-kaida eine bombe gezündet hat, aber nicht durch softwarefehler. das ist absolut inakzeptabelpointercrash() schrieb:
Üblicherweise verzweige ich auf eine Routine, die die Hardware erstmal gesichert abschaltet.
für mich als kunde wäre das gerät damit kaputt und ich würde mein geld zurückverlangen
pointercrash() schrieb:
Besser: Einen unkritischen Pin als TX einer async serial verwenden und den Returnstack darüber ausgeben. Naja, und beten, daß das Ding wirklich noch soviel tut ...
wenn wir mit BDM das gleiche meinen (background debug mode): das ist auch noch funktional, wenn die ganze software abgestürzt ist. da kannste z.b. einen datenlogger anschliessen und den stack, registerinhalte usw. mitloggen, wenn dein programm gecrasht ist.
pointercrash() schrieb:
aber wenn Du aufwendige MMIs ins System schleifen mußt, weil Dein Kunde das System geschwätziger haben will, mehrsprachig und die Dudeltöne selbst konfigurieren will, rutscht auf einmal viel mehr Zeug durchs System.
Den Vorgänger habe ich vor 11 Jahren in 1800 Byte Assembler programmiert, der Nachfolger hat vollständig über Systemmenü konfigurierbare Hardware (jumperless) und kann englisch, holländisch, deutsch, bedarfsweise die Marseillaise dudeln und braucht momentan fast 38 kB ROM :p .naja, aber das stelle ich mir halb so wild vor. die sounddaten können doch direkt aus dem rom gelesen werden, oder? wofür braucht man da malloc/free?
pointercrash() schrieb:
aber wenn mir auf dem Controller der Platz ausgeht, nehm' ich einfach schneller & größer, pinkompatibel. Ein funktionierendes Konzept zu kippen, wäre teurer.
so einen controller gibt es meistens nicht. oft hat jedes derivat eine andere pinbelegung. mir ist's z.b. schon mal passiert, dass ein controllertyp plötzlich lieferzeiten von 3 monaten hatte, so dass ich ein neues boardlayout machen musste, um einen einigermassen kompatiblen typen einzusetzen.
zeit ist geld und die produktion muss weitergehen...pointercrash() schrieb:
Eigentlich vermisse ich an C das Fehlen einer Anweisung, die eine "garbage collection" durchführt.
kannst ja von zeit zu zeit den heap neu initialisieren
-
pale dog schrieb:
oh, BDM? benutzt du einen freescale?
Nöh, können auch andere.
pale dog schrieb:
... ist absolut fatal. mikroprozessorschaltungen dürfen vielleicht versagen, ... aber nicht durch softwarefehler. das ist absolut inakzeptabel
Und trotzdem gibt es Windows CE ... heißt mittlerweile anders, ist aber trotzdem Träger von SPS- Applikationen.
pale dog schrieb:
für mich als kunde wäre das gerät damit kaputt und ich würde mein geld zurückverlangen
Wie gut, daß ich mit Endkunden nix am Hut habe
Die Zwischenhändler wollen nur, daß ich's flott heile mache, wenn mal was schiefgeht. Die Endkunden überwiegend wohl auch. Und die Zwischenhändler sollen auch mal was für ihren Aufschlag tun ...
pale dog schrieb:
wenn wir mit BDM das gleiche meinen (background debug mode): das ist auch noch funktional, wenn die ganze software abgestürzt ist. da kannste z.b. einen datenlogger anschliessen und den stack, registerinhalte usw. mitloggen, wenn dein programm gecrasht ist.
Leider nimmer, wenn's schon draußen ist
. Für'n JTAG- Stecker ist nicht auf jedem Layout Platz, ein Extra- Lötauge kriege ich leichter unter.
pale dog schrieb:
naja, aber das stelle ich mir halb so wild vor. die sounddaten können doch direkt aus dem rom gelesen werden, oder? wofür braucht man da malloc/free?
Es positioniert Schrittmotore, während der Sch* dudelt, das Display kann auch nur zu bestimmten Zeiten Daten entgegennehmen. Da stauen sich schon Anweisungslisten ...
pale dog schrieb:
so einen controller gibt es meistens nicht. oft hat jedes derivat eine andere pinbelegung. mir ist's z.b. schon mal passiert, dass ein controllertyp plötzlich lieferzeiten von 3 monaten hatte, so dass ich ein neues boardlayout machen musste, um einen einigermassen kompatiblen typen einzusetzen.
Ja, das ist schwierig, kenn' ich auch, deswegen rate ich bei kleineren Stückzahlen, nicht auf den halben EUR zu schauen und auf eine weit skalierende Prozessorfamilie zu setzen. Aber Kundenerziehung ist so eine Sache ...
pale dog schrieb:
kannst ja von zeit zu zeit den heap neu initialisieren
Aye, hab's gemerkt, leider fehlt mir der Standard, den Heap zu initialisieren
'ne Idee?
-
pointercrash() schrieb:
Leider nimmer, wenn's schon draußen ist
. Für'n JTAG- Stecker ist nicht auf jedem Layout Platz, ein Extra- Lötauge kriege ich leichter unter.
JTAG braucht mindestens 6 pins, BDM kommt mit nur 2 pins aus
aber wir meinen ja beide sowieso nicht das selbe...pointercrash() schrieb:
Ja, das ist schwierig, kenn' ich auch, deswegen rate ich bei kleineren Stückzahlen, nicht auf den halben EUR zu schauen und auf eine weit skalierende Prozessorfamilie zu setzen.
ach, die hersteller haben keine problem damit, einen controller einfach so abzukündigen z.b. wenn die verkaufszahlen rückläufig sind oder so.
pointercrash() schrieb:
pale dog schrieb:
kannst ja von zeit zu zeit den heap neu initialisieren
Aye, hab's gemerkt, leider fehlt mir der Standard, den Heap zu initialisieren
'ne Idee?
war eigentlich als scherz gemeint, aber wenn du unbedingt willst: mach beim build ein mapfile mit allen infos, da findest du dann auch die 'heap_init()' funktion (der name kann bei dir natürlich anders lauten), und die ruftste dann einfach auf. sie braucht wahrscheinlich zwei parameter, einen pointer auf den heapspeicher und eine grössenangabe...
aber dass dann natürlich alle bisherigen 'mallocs' hinfällig sind, ist dir doch wohl klar?
-
pale dog schrieb:
JTAG braucht mindestens 6 pins, BDM kommt mit nur 2 pins aus
aber wir meinen ja beide sowieso nicht das selbe...
BDM ist das erste System mit On- Chip- Debugfähigkeiten, vor Ewigkeiten eingeführt durch Motorola. Da ist nix Standard, auch kein Freescale- Pinning, sondern lediglich die grundsätzliche Fähigkeit gemeint, auf die Kiste noch zugreifen zu können, wenn alle Software gecrasht ist. Siehe http://www.netrino.com/Publications/Glossary/BDM.php
pale dog schrieb:
ach, die hersteller haben keine problem damit, einen controller einfach so abzukündigen z.b. wenn die verkaufszahlen rückläufig sind oder so.
Kann mich nicht beschweren, die "Last Buy"- Announcements kamen bei Mitsubishi/Renesas wenigstens auf 12 Monate vorab. Allerdings haben die auch im Zuge von ROHS das Sortiment schwer ausgelichtet und die "10 Years availability" mal um gute zwei Jahre gekürzt.
pale dog schrieb:
war eigentlich als scherz gemeint, ...
deswegen:
pointercrash() schrieb:
Aye, hab's gemerkt, leider fehlt mir der Standard, den Heap zu initialisieren
'ne Idee?
pale dog schrieb:
... aber dass dann natürlich alle bisherigen 'mallocs' hinfällig sind, ist dir doch wohl klar?
Ist wohl ein bißchen brutal; klingt, als müßte man seinen Kindern die Füße abhacken
, wenn man das Nachkaufen größerer Schuhe leid ist ...
Aber um es mal auf eine Sinnfrage jenseits der Blödelei
zu bringen: Warum wurde auf einen Standardaufruf zum Aufräumen / Defragmentieren des Heaps verzichtet?
-
pointercrash() schrieb:
BDM ist das erste System mit On- Chip- Debugfähigkeiten, vor Ewigkeiten eingeführt durch Motorola. Da ist nix Standard, auch kein Freescale- Pinning, sondern lediglich die grundsätzliche Fähigkeit gemeint, auf die Kiste noch zugreifen zu können, wenn alle Software gecrasht ist.
das hab' ich auch gerade festgestellt, beim coldfire sind es 3 pins, ich dachte immer wenigstens das hardware-protokoll wäre gleich bei allen BDM's, ist aber offensichtlich nicht so.
pointercrash() schrieb:
pale dog schrieb:
ach, die hersteller haben keine problem damit, einen controller einfach so abzukündigen z.b. wenn die verkaufszahlen rückläufig sind oder so.
Kann mich nicht beschweren, die "Last Buy"- Announcements kamen bei Mitsubishi/Renesas wenigstens auf 12 Monate vorab.
ja, aber doof wird's erst, wenn man alle distributoren abklappern muss, weil die teile einfach ausverkauft sind, obwohl sie noch produziert werden. abhängig von vorherigen käufen füllen die grosshändler ihre lagerbestände auf und wenn auf einmal mehr gekauft wird, als kalkuliert wurde, können engpässe von mehreren wochen entstehen und das kann immer passieren.
beschaffung von hi-tech bauteilen ist oft sehr schwierig für kleine firmen. bei den grossen ist das anders, die ordern direkt beim hersteller einige millionen bauteile und bei solchen stückzahlen können die sich sogar custom-chips ohne aufpreis basteln lassen...