Hallo Leute,
ich rufe eine Funktion in zwei unterschiedlichen Funktionen auf. In dem
einen Fall verhält sich die Funktion wie erwartet, in dem anderen Fall
nicht. Das äußert sich in undefinierten Verhalten des Programms
einschließlich Reset.
... ziemlich ratlos ...
Malte
--- file.h ---
void LiPoOptions(struct sMenu* pMenu);
void func2(void);
--- use1.c ---
main(){
printf("%p", &LiPoOptions); // --> 0x3694
LiPoOptions(); // geht
func2();
}
func2(){
printf("%p", &LiPoOptions); // --> 0x3694
LiPoOptions(); // geht nicht (s.u.)
.... bla bla ...
}
void LiPoOptions() {
lcd_clr(); // geht
LCDSoftChar('a', 0, 0); // geht
printf("\nOptions\n"); // geht nicht
}
Malte wrote:
> void LiPoOptions(struct sMenu* pMenu);>> main(){> printf("%p", &LiPoOptions); // --> 0x3694> LiPoOptions(); // geht
Wundert mich, dass das geht. Es fehlt doch das Funktionsargument aus dem
Funktionsprototypen.
Bitte poste dein wirkliches Programm und nicht ein extra
für dieses Forum zurechtgestricktes Beispiel. Zu deinem
Problem gibt es 100-erte Möglichkeiten was da schief
gelaufen sein kann. Da brauchen wir nicht auch noch Fehler
die du beim Tippen in diesem Forum eingefügt hast.
Wenn du denkst, dass dein Programm zu lang ist, dann specke es
ab. Stell aber sicher, dass der Fehler noch im Programm ist.
Aber: Auf keinen Fall, auf gar keinen Fall solltest du ein
Programm hier eintippen sondern immer den tatsächlichen
Quelltext veröffentlichen. Entweder indem du die Dateien anhängst,
oder indem du mittels Cut&Paste den Code einstellst.
Erst mal sorry, ich wollte euch nicht mit dem gesamtem Code belästigen.
Habe den Beitrag dann beim Testen gestern mehrfach überarbeitet und
offenbar Fehler eingebaut...
Das mit dem Stacküberlauf kam mir dann auch heute Nacht. Ich habe eben
mal den freien Speicher bestimmt. Dieser liegt zunächst bei 438 Byte.
Was mir dabei auffällt ist das der Funtktionsaufruf (jeweile) eine Menge
Stack verbraucht. Soviel das dabei (sehr wahrscheinlich) ein Stack
overflow auftritt. Der Stackverbrauch für den Funktionsaufruf ( Funktion
s.u. ) liegt so bei 65 Byte wobei mir die Quelle dafür unklar ist.
(Die Funktion ist etwas gestripped und enhält normalerweise mehrere
Menuelemente. Jedes scheint auf dem Stack zu landen - d.h. der
Speicherverbrauch ist im Regelfall höher)
Verwendet habe ich folgende Methode um den freien Speicher zu bestimmen.
http://www.roboternetz.de/wissen/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc#Dynamischer_RAM-Verbrauch
Codeschnipsel (kopiert)
typedef struct {
enum eElementType ElementType;
} tElement;
typedef struct sMenu {
int v;
int numEl;
tElement** el;
} tMenu;
typedef struct {
enum eElementType ElementType;
char text[LCD_DISP_LENGTH];
float v;
float min;
float max;
float gran;
} tFloatParameter;
void LiPoOptions (void) {
uint8_t mmEntries = 0;
tElement* MenuElements[MAX_OPT_MENU_ENTRIES];
tFloatParameter DisChgCellVlim = {FLOAT_PARAM, "Entl. Sp. %4.1f
V", 2.5, 4.2, 3.0};
MenuElements[mmEntries++] = (tElement*)&DisChgCellVlim;
tMenu Menu = {0, mmEntries, MenuElements};
sub_menu(&Menu);
}
Beim Zugriff auf den Text dann die pgm_readxxxx bzw. (der Text sieht
mir danach aus, als ob er direkt für printf benutzt wird) printf_p
benutzen. printf_p erwartet den Formatstring im Flash.
LCD_DISP_LENGTH ist 21
sizeof(tFloatParameter) ist 39.
Mir ist klar das ich mit dem SRAM sehr "großzügig" umgehe und das es
bessere Methoden gibt hier solche Daten zu speichern.
Nicht klar ist mir warum die Struktur DisChgCellVlim auf dem Stack zu
landen scheint. Die Funktion hat normalerweise 3 Menuelemente und
verbraucht dann 147 bytes auf dem Stack. Das ganze geht in dem Programm
bis 10 Menuelemente. Das sind dann >390byte auf dem Stack. Dazu kommt
das es Untermenus gibt, sich das ganze also addiert.
Warum?
Noch ein Nachtrag:
Mache ich die struktur tFloatParameter DisChgCellVlim global dann
schrumpft der Stack um eine zu erwartende Grösse. Die Section .data wird
um 38 Byte grösser. Könnte also passen. Das würde, mein Verständniss
vorausgesetzt, bedeuten das das struct DisChgCellVlim wirklich im Stack
liegt.
Klingt fast wie die Verwendung von __builtin_alloca
Ich habe mir das Assemblerlisting angesehen, bin aber da zu wenig
bewandert um das wirklich zu verstehen.
Gruß
Malte
> Erst mal sorry, ich wollte euch nicht mit dem gesamtem Code belästigen.
Das ist ja im Prinzip eine gute Idee, aber man sollte nie als Teil der
Fehlerbeschreibung Code angeben, der nur für das Posting neu eingetippt
wurde. Der enthält erfahrungsgemäß oft nicht den Fehler, um den es geht,
dafür aber jede Menge andere Fehler. Also immer Code posten, den du auch
tatsächlich mal so durch den Compiler hast laufen lassen.
> Nicht klar ist mir warum die Struktur DisChgCellVlim auf dem Stack zu> landen scheint.
Lokale Variablen werden eben (so sie zu groß für Register sind) im Stack
angelegt. Wo hättest du sie erwartet?
Eigentlich ist es auch egal, ob die Variablen auf dem Stack oder sonstwo
im SRAM landen - es gibt nur ein SRAM, und ob das nun von oben nach
unten, oder von unten nach oben überläuft, ändert am Ergebnis nichts.
Oliver