Forum: Mikrocontroller und Digitale Elektronik Speicherüberlauf?


von Stefan S. (stefanst)


Lesenswert?

Hallo µC-Bändiger!
Ich habe ein Programm für den AN2131 von Cypress geschrieben, dessen 
Verhalten ich bisher (meistens zumindest) verstanden habe. Doch jetzt 
passiert mir etwas sehr seltsames: Wenn ich folgende Funktion in meinem 
Programm aufrufe, "spinnt" es, wenn die Variable zzz ein int ist, wenn 
sie ein unsigned char ist, funktioniert es (zumindest scheint es so...)
1
char test(){
2
  unsigned char xxx;
3
  int zzz;
4
  //unsigned char zzz;
5
  xxx=4;
6
  zzz=5;
7
  return "a";
8
}

Liegt das Problem vielleicht in einer Art "Speicherüberlauf"?

Mit hoffenden Grüßen,
elko

von (prx) A. K. (prx)


Lesenswert?

Wenn du mit "spinnst" eine Meldung des Compilers meinst: "a" ist ein 
String, kein Zeichen (char). Das wäre 'a'.

von Stefan S. (stefanst)


Lesenswert?

Ähm, nein, das "a" hatte ich nur zu testzwecken eingesetzt... mit 
"spinnen" meine ich, dass sich das Programm -soweit man das von außen 
beurteilen kann- aufgehängt hat (wie windoof...)

grüße

von Karl H. (kbuchegg)


Lesenswert?

Dann wirst du wohl noch einen Fehler im Programm haben.
Allerdingfs sitzt der Fehler nicht in dieser Funktion. Dort macht er 
sich nur bemerkbar.

von Stefan S. (stefanst)


Lesenswert?

Aber warum soll er sich in der Funktion bemerkbar machen, wenn sie doch 
eigentlich nicht s macht und auch keine Daten von außen verwertet? Vor 
allem: Wieso soll er auftreten, wenn zzz ein int ist und wenn zzz ein 
char ist, tut er es nicht?!

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Stefan S. schrieb:
> allem: Wieso soll er auftreten, wenn zzz ein int ist und wenn zzz ein
> char ist, tut er es nicht?!
z.B. weil ein (lokaler) char oft nur 1 byte auf dem Stack benötigt, ein 
int aber häufig 2 oder 4 bytes.

von Stefan S. (stefanst)


Lesenswert?

Eben genau deswegen verstehe ich nicht, warum der Fehler woanders im 
Programm liegen soll: Tritt das Problem nur auf, wenn man char gegen int 
austauscht, so vermut ich, dass das Problem ggf. an einem 
Speicherüberlauf oder so etwas in der Richtung liegt... aber wie kann 
ich das Problem lösen (falls es dies ist)?

Viele Grüße,
Stefan

von Experte (Gast)


Lesenswert?

a.) Welcher Compiler und welche Einstellungen?

b.) Wie oben schon geschrieben wurde, Rückgabewert und Deklaration 
passen nicht zusammen.

c.) Wenn der Compiler nicht strunze-dumm ist und Optimierungen 
eingeschlatet sind, werden die Zuweisungen ersatzlos weg optimiert da 
sie nie benutzt werden.

d.) Wenn der Compiler nicht strunze-dumm ist und Optimierungen 
eingeschlatet sind, wird die verbleibende Funktion komplett inlined, 
weil sie trivial ist.

e.) Wie oben schon geschrieben: Das Problem sitzt in 99,9999% der Fälle 
vor dem Computer und versucht den Compiler zu benutzen. Du hast irgendwo 
anders im Programm in Bug.

f.) Wenn Du einen Fehler hast bei dem der C-Standart sagt, das Verhalten 
ist undefiniert, darf der Compiler machen was er will, auch solche 
lustigen Dinge wie Du beschreibst.


Fazit: Bring Deinen restlichen Code auf Vordermann. Vermutlich ist der 
total verbugt.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Stefan S. schrieb:
> Ähm, nein, das "a" hatte ich nur zu testzwecken eingesetzt... mit
> "spinnen" meine ich, dass sich das Programm -soweit man das von außen
> beurteilen kann- aufgehängt hat (wie windoof...)
Woran erkennst Du, dass sich Dein Programm genau in dieser Funktion 
aufhängt?

von Stefan S. (stefanst)


Lesenswert?

Experte schrieb:
> a.) Welcher Compiler und welche Einstellungen?
µVision3 von Keil
zu den Einstellungen kann ich um ehrlich zu sein kein Kommentar abgeben 
(kenne mich nicht soooo gut mit dem Compiler aus und weis nicht, was du 
meinst...)

> b.) Wie oben schon geschrieben wurde, Rückgabewert und Deklaration
> passen nicht zusammen.
Auch wenn ich zB 5 zurückgebe, funktioniert das Programm nicht

> c.) Wenn der Compiler nicht strunze-dumm ist und Optimierungen
> eingeschlatet sind, werden die Zuweisungen ersatzlos weg optimiert da
> sie nie benutzt werden.
> d.) Wenn der Compiler nicht strunze-dumm ist und Optimierungen
> eingeschlatet sind, wird die verbleibende Funktion komplett inlined,
> weil sie trivial ist.
Das denke ich nicht, denn Programsize ändert sich, wenn ich den Code in 
der Funktion test() weglasse.

> e.) Wie oben schon geschrieben: Das Problem sitzt in 99,9999% der Fälle
> vor dem Computer und versucht den Compiler zu benutzen. Du hast irgendwo
> anders im Programm in Bug.
Da stimme ich dir zu... [ironie] aus dem Fenster spring = Problem 
beseitigt [/ironie]

> f.) Wenn Du einen Fehler hast bei dem der C-Standart sagt, das Verhalten
> ist undefiniert, darf der Compiler machen was er will, auch solche
> lustigen Dinge wie Du beschreibst.
Meinst du wirklich, dass ein solches Verhalten auf "normale" 
Programmierfehler zurückzuführen ist?

> Fazit: Bring Deinen restlichen Code auf Vordermann. Vermutlich ist der
> total verbugt.
Das kann ich mir wiederum auch gut vorstellen... Ich würde auch das 
ganze Programm nochmals überarbeiten, aber dazu wäre es sinnvoll, dass 
ich den Programmablauf "live" mitverfolgen kann. Doch da in dem 
Programm, das unter anderem 1en und 0en für ein 
Onewire-Übertragungsprotokoll generiert, viele Schleifen vorhanden sind 
(eben auf Grund der Erzeugung der verschieden langen 1en und 0en), ist 
ein Debuggen meines erachtens sehr schwierig... hast du (oder jemand 
anders) eine Idee, wie ich mehr Kontrolle über den Programmablauf 
bekommen kann?

Viele Grüße,
Stefan

von Karl H. (kbuchegg)


Lesenswert?

OK. Da du nicht begreifen willst und es anscheinend nicht reicht es dir 
durch die Blume zu sagen:

*************************************************************
Wenn du hiernei Hilfe haben möchtest, dann poste den kompletten Code!
Dein Fehler sitzt nicht in dieser Funktion.
*************************************************************


Vergiss die Idee, dass der Compiler einen Fehler gemacht hat. Zu 99.9% 
ist der Fehler immer im Programm. Nur Neulinge denken, dass sie mit 
ihrem cleveren Code einen Compilerfehler entdeckt haben, den vor ihnen 
noch nieeee irgendwer anderer gesehen hat. In Wirklichkeit sind es 
meistens irgendwelche Array-Overflows, mit denen der Stack zerschossen 
wird oder sonst irgendwelche banalen Dinge, wie zb Unverständnis wie 
Stringverarbeitung in C wirklich funktioniert.

> Meinst du wirklich, dass ein solches Verhalten auf "normale"
> Programmierfehler zurückzuführen ist?

Wenn du Sicherheit vor dir selbst haben willst, dann ist C die falsche 
Sprache für dich. C funktioniert nach dem Muster: You asked for it, you 
got it.

Nur so als Zwischenfrage: Besitzt du eigentlich ein C-Buch, welches dir 
Schritt für Schritt beibringt, was du tun darfst, was nicht und wie man 
bestimmte Dinge löst bzw. worauf man achten muss. Das ist nämlich der 
nächste Fehler: zu glauben man könnte eine Programmiersprache ohne 
vernünftige Literatur aus dem Stegreif lernen.

>> Fazit: Bring Deinen restlichen Code auf Vordermann. Vermutlich ist
>> der total verbugt.
> Das kann ich mir wiederum auch gut vorstellen... Ich würde auch
> das ganze Programm nochmals überarbeiten, aber dazu wäre es
> sinnvoll, dass ich den Programmablauf "live" mitverfolgen kann.

Das ist Quatsch.
Sinnvoll ist es, den Code in Funktionen aufzuteilen und sich an die 
simple Weisheit zu halten: Eine Funktion soll nur das tun, was aussen 
drauf steht. Ist die Funktionalität innerhalb der Funktion trivial, dann 
bleibt die Funktion so. Ist sie komplexer, so wird auch diese Funktion 
wieder in Unterfunktionen aufgeteilt, solange bis Funktionen kein 
Spaghetticode mehr sind, sondern so übersichtlich, dass man sich durch 
Hinschauen von der Korrektheit des Verfahrens überzeugen kann. Danach 
(oder gleichzeitig) geht man jede Funktion durch und überzeugt sich 
davon, dass alle Regeln der Sprache eingehalten wurden.
Dazu musst du dein Programm meistens noch nicht einmal laufen haben. Um 
zu Prüfen, ob die Sprachregeln eingehalten wurden, ist Laufenlassen 
sowieso der schlechteste Weg. Denn wie schon gesagt hat der Compiler 
eine ganze Menge Spielraum und kann auch bei vielen Regelverletzungen 
immer noch Code erzeugen, der auf den ersten Blick sauber läuft aber in 
speziellen Situationen kläglich versagt. Ein gutes, korrektes Programm 
fängt immer damit an, dass man sauberen Code hat. Und das fängt bei ganz 
banalen formalen Dingen an: gute Variablennamen, saubere Einrückungen, 
lesbarer Code. Wenn ich schon Variablennamen wie xxx und zzz sehe, will 
ich mir lieber nicht vorstellen, wie der Rest vom Code aussieht.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Was auch immer hilfreich ist, ist den generierten Assembler-Code 
anzusehen. Da sieht man dann genau, was der Compiler aus seinem Code 
gemacht hat.

Wenn das Programm, wie in Deinem Fall (wenn es denn wirklich so ist), 
hängen bleibt (Hängen ist immer eine Endlosschleife, bei der etwas 
passiert, was nicht von aussen sichtbar ist), so hat zu 99% der 
Stack-Pointer etwas damit zu tun. Denk dran, dass dieser nicht endlos 
groß ist. Speziell bei rekursiven Aufrufen läuft der schnell über. Bei 
einem PC gibt es hierzu Überwachungsroutinen, die Dich vorher warnen. 
Ein µC hat solche Routinen nicht. Der PC springt dann womöglich irgendwo 
hin und landet dann in einer Schleife.

Läuft der Stack über, fängt er normalerweise wieder unten an und 
überschreibt entweder Programmvariablen oder auch wiederum den Stack 
selber.
Kommt drauf an, wie der Prozessor das handhabt.

Es ist übrigens gut möglich, ein Assemblercode manuell (also auf dem 
Papier/Editor) zu durchlaufen. Das machst Du für jede Funktion und 
schreibst Dir die Speicherzustände mit (auch den PC und SP).

von Stefan S. (stefanst)


Lesenswert?

Karl heinz Buchegger schrieb:
> *************************************************************
> Wenn du hiernei Hilfe haben möchtest, dann poste den kompletten Code!
> Dein Fehler sitzt nicht in dieser Funktion.
> *************************************************************
gerne. Ich will dir nichts vorenthalten, aber ich kann mir vorstellen, 
dass das nicht einfach ein "drübergucken - da ist der Fehler!" wird... 
aber ich will keine voreiligen Schlüsse ziehen ;-)

> Vergiss die Idee, dass der Compiler einen Fehler gemacht hat. Zu 99.9%
> ist der Fehler immer im Programm. Nur Neulinge denken, dass sie mit
> ihrem cleveren Code einen Compilerfehler entdeckt haben, den vor ihnen
> noch nieeee irgendwer anderer gesehen hat.
das habe ich auch schon öfters festegestellt... Und ich bin mir sicher, 
dass ich einen Fehler gemacht habe, aber WIESO kann es überhaupt 
passieren, dass bei einer Änderung einer Variable von char zu int in 
einer Funktion, die absolut NIE aufgerufen wird, eine Änderung des 
Programmablaufes zur Folge hat???

> Nur so als Zwischenfrage: Besitzt du eigentlich ein C-Buch, welches dir
> Schritt für Schritt beibringt, was du tun darfst, was nicht und wie man
> bestimmte Dinge löst bzw. worauf man achten muss. Das ist nämlich der
> nächste Fehler: zu glauben man könnte eine Programmiersprache ohne
> vernünftige Literatur aus dem Stegreif lernen.
ich habe schon einige Bücher gewälzt (Grundlagen...) und verstanden 
(okay, was man nicht täglich anwendet vergisst man... zB 
Stringverarbeitung bei µC)

>>> Fazit: Bring Deinen restlichen Code auf Vordermann. Vermutlich ist
>>> der total verbugt.
>> Das kann ich mir wiederum auch gut vorstellen... Ich würde auch
>> das ganze Programm nochmals überarbeiten, aber dazu wäre es
>> sinnvoll, dass ich den Programmablauf "live" mitverfolgen kann.
>
> Das ist Quatsch.
denke ich nicht, denn dann könnte ich vielleicht endlich sehen, wo sich 
das Programm "aufhängt" (oder sonstwas tut...

> Ein gutes, korrektes Programm
> fängt immer damit an, dass man sauberen Code hat. Und das fängt bei ganz
> banalen formalen Dingen an: gute Variablennamen, saubere Einrückungen,
> lesbarer Code. Wenn ich schon Variablennamen wie xxx und zzz sehe, will
> ich mir lieber nicht vorstellen, wie der Rest vom Code aussieht.

Darauf habe ich geachtet, nur nach stundenlangem Fehlersuchen und 
zahlreichen vergeblichen Änderungen mache ich mir keine Gedanken, wie 
ich Variablen in einer Funktion zu testzwecken nenne... (ein dreifaches 
z baut die dreifache Menge an Agressionen ab ;-))

Wäre schön, wenn du mir nen Tipp geben kannst ;-)

Gruß,
Stefan

@ Christian: Ich werde demnächst auch mal versuchen, den Code nochmals 
komplett zu überarbeiten

von Stefan S. (stefanst)


Angehängte Dateien:

Lesenswert?

der Upload...

von Karl H. (kbuchegg)


Lesenswert?

Wieviel Speicher hat das Ding?

Du allocierst du eine Menge Holz global

von (prx) A. K. (prx)


Lesenswert?

Karl heinz Buchegger schrieb:

> Wieviel Speicher hat das Ding?
> Du allocierst du eine Menge Holz global

So arg viel ist es nicht. Das Teil hat effektiv knapp 7KB RAM und das 
Program verbrät keine 400. Der Compiler platziert xdata zwar erst ab 
0x800 und verschenkt damit 2KB, das ist aber letztlich immer noch egal. 
Der explizit ab 0x0119 platzierte Variablenblock erschliesst sich mir 
auch nicht, sollte aber ebenfalls dabei keine Rolle spielen.

Nur frage ich mich dann schon, welchen Sinn diese auf den ersten Blick 
nicht sehr zum Controller passend scheinende Speicherverteilung und 
dieser merkwürdig anmutendene Variablenblock haben. Ob da irgendwas quer 
konfiguriert ist. Allerdings habe ich von der Doku des Controllers nur 
ein paar Seiten quergelesen, vielleicht hat das ja einen Sinn.

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.