www.mikrocontroller.net

Forum: Compiler & IDEs Zu viele Pointer - brauche Hilfe.


Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

ich habe eine Funktion geschrieben um NMEA-Daten zu parsen. Die Funktion 
wird mit
ParseMessage(nmeastring, stringtype, &NavState);
aufgerufen, wobei die geparsten Daten dann im Struct NavState landen 
sollen. ParseMessage() funktioniert soweit perfekt und dekodiert wie 
gewünscht. Allerdings tauchen in der main() keine Daten in NavState auf, 
obwohl sie in ParseMessage() reingeschrieben werden. Was hab ich denn da 
übersehen? Die Daten im Struct scheinen uninitialisiert zu sein.

typedef struct navstruct
{
  int newdata;
  double time;
} navstruct;

void ParseMessage(char *, int, navstruct *);
void ParseField(char **, char *);

int main(void)
{
  navstruct NavState;
  char dispbuff[33];
  ...
ParseMessage("$GPGGA,190533.920,4806.0000,N,01117.0000,E,1,09,0.9,475.3,M,47.8,M,,0000*5C", GGA, &NavState);
  ...
  sprintf(dispbuff, "%d %d", NavState.newdata, (int)NavState.time);
  lcd_puts(dispbuff);
  ...
}

void ParseMessage(char * Message, int NMEA, navstruct * pNavState) {
  char * pMessage;
  char TempBuff[10]; 

  pMessage = Message;
  ParseField(&pMessage, TempBuff);
  pNavState->time = atof(TempBuff);
  pNavState->newdata = 1;
}

Autor: Thomas Decker (t0mmy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein struct sieht komisch aus. Du benutzt 2x die Bezeichnung 
"navstruct".
Schau mal bei http://c-buch.sommergut.de/Kapitel13/Strukturen.shtml wie 
das gemacht werden muss. Ich hab mich da auch schon vertan.
Je nachdem ob mit oder ohne typedef steht Objektname oder Instanzname 
(falls vorhanden) woanders.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auch
typedef struct navstruct_xy
{
  int newdata;
  double time;
} navstruct;
oder
typedef struct
{
  int newdata;
  double time;
} navstruct;
ändert leider nichts an der Sache.
Mit nem volatile struct hatte ich auch keinen Erfolg. Ich hab ein 
bisschen den Verdacht dass ich mich da mit dem referenzieren und 
dereferenzieren irgendwo vertan hab, aber ich find keinen Fehler...

Autor: Thomas Decker (t0mmy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ParseField(&pMessage, TempBuff);
pMessage ist schon eine Referenz, da brauchst du das & nicht. Sonst hab 
ich nix entdeckt.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, das passt schon so, die Funktion ParseField muss den Pointer 
pMessage ändern können, deswegen char **. Problem ist dass die Daten, 
die ich in ParseMessage in den struct reinschreibe in der main Funktion 
nicht ankommen.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Verwendung von ParseField entspricht dem Prototyp und die 
Strukturdefinitionen sind und waren auch ok.

Bist du sicher daß der RAM nicht ausgeht? Und bei einem der 
Funktionsaufrufe mit dem Riesenstring oder bei atof/sprintf ein Teil des 
RAMs/Stacks überschrieben wird?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ParseMessage("$GPGGA,190533.920,4806.0000,N,01117.0000,E,1,09,0.9,475.3,M,47.8,M,,0000*5C", GGA, &NavState);
  ...
  sprintf(dispbuff, "%d %d", NavState.newdata, (int)NavState.time);
Und aus was besteht "..."? Wird da vielleicht auch nach dispbuff 
geschrieben?

Autor: Thomas Decker (t0mmy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh stimmt, die ** sind mir zwar aufgefallen, aber muss ich wieder 
verdrängt haben. Mir fällt sonst nichts weiter ein.

Autor: Tonne (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
typedef struct navstruct_xy
{
  int newdata;
  double time;
} navstruct;
...
int main(void)
{
  navstruct_xy NavState;
...
??

Autor: Walter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Nein, das passt schon so, die Funktion ParseField muss den Pointer
>pMessage ändern können, deswegen char **. Problem ist dass die Daten,
>die ich in ParseMessage in den struct reinschreibe in der main Funktion
>nicht ankommen.
ist zwar nicht der Fehler, naber warum muss sie pMessage ändern können 
wenn die Änderung nirgends beachtet wird?

Autor: Tonne (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups, dort natürlich dann auch:
void ParseMessage(char * Message, int NMEA, navstruct_xy * pNavState) {
oder besser gleich
typedef struct navstruct
{
  int newdata;
  double time;
} ;
...
int main(void)
{
  navstruct NavState;
...
}
...
void ParseMessage(char * Message, int NMEA, navstruct * pNavState) {
...
oder so

mfg

Autor: Tonne (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Müll geschrieben, steht ja schon "typedef" davor, sorry

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich sehe an den Fragmenten kein Problem.
Kannst du mal ein (am besten auf PC) kompilierbares vollständiges
Programm liefern?

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich mach heut abend mal ein kompilierbares Beispiel. Ich hab mir den 
Assembler-Code angeschaut, bin aber daraus auch nicht recht schlau 
geworden. Es scheint als ob er das gleiche Register (Z) sowohl für 
TempBuff als auch den Struct verwendet. Das wundert mich zwar etwas, 
aber grundsätzlich sollte da ja auch nichts dagegensprechen das mit 
unterschiedlichen Offsets zu machen.


Walter:
> ... ist zwar nicht der Fehler, naber warum muss sie pMessage ändern
> können wenn die Änderung nirgends beachtet wird?
Weil mein Code-Ausschnitt nur fürs Problem relevante Teile enthält, im 
vollständigen Programm hat das schon so seine Richtigkeit :-)

Johann:
> Bist du sicher daß der RAM nicht ausgeht? Und bei einem der
> Funktionsaufrufe mit dem Riesenstring oder bei atof/sprintf ein Teil des
> RAMs/Stacks überschrieben wird?
Eigentlich schon, der Code läuft auf nem Mega328. Aber ich probiers 
später mal mit nem kürzeren String.

Stefan:
> Und aus was besteht "..."? Wird da vielleicht auch nach dispbuff
> geschrieben?
Nein.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So, hab ein Progrämmchen zum kompilieren aufm PC draus gemacht. Ganz 
toll ist natürlich, dass die Sache auf dem PC einwandfrei funktioniert.

Daraufhin hab ich ein bisschen weiterprobiert:
Wenn ich ParseMessage verändere:
void ParseMessage(char * Message, int NMEA, navstruct * pNavState) {
  char * pMessage;
  char TempBuff[10]; 

  pMessage = Message;
  ParseField(&pMessage, TempBuff);
  pNavState->time = atof(TempBuff);
  pNavState->newdata = 1;
 
 dtostrf(pNavState->time, 6, 3,outbuff); 
 uart_puts_P("ParseMessage() ");
 uart_puts(outbuff);
}
dann kommt auch tatsächlich in der Main der gewünschte Wert an. Wenn ich 
die Zeile weglasse scheint es dass der Struct wegoptimiert wird. Ein 
deklarieren von NavStruct als volatile ändert leider auch nichts an der 
Sache. Hat noch jemand Ideen?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
welche Zeile?
welches NavStruct?
wo ist der restliche Quelltext?

Autor: Gast (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier ist mal ein lauffähiger Code für den Mega 328. So wie gepostet 
funktionierts, Zeile 83 bis 85 auskommentiert gehts nicht mehr. Der Uart 
Treiber is von Peter Fleury. Leider kann ich es nicht auf dem PC 
demonstrieren, da sich da der Fehler einfach weigert aufzutreten.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
TempBuf in ParseMessage ist zu klein. Beim zweiten Feld (190533.920) (*) 
landet die terminierende Null daher außerhalb des Arrays.

(*): Und auch beim fünften, wenn du denn so weit Parsen würdest.

PS: Vielleicht möchtest du dir ja mal die Funktion strtok anschauen.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tatsache, das Feld ist zu kurz... Jetzt gehts. Danke!
Der Tipp mit strtok ist gut, die kannte ich noch nicht. Aber jetzt gehts 
ja, d.h. die Funktion wird mal gespeichert und beim nächsten 
gleichartigen Problem wieder rausgekramt :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gast schrieb:
> Tatsache, das Feld ist zu kurz... Jetzt gehts. Danke!
> Der Tipp mit strtok ist gut, die kannte ich noch nicht. Aber jetzt gehts
> ja, d.h. die Funktion wird mal gespeichert und beim nächsten
> gleichartigen Problem wieder rausgekramt :-)

Wenn du diese Funktion in deine persönliche Library übernehmen willst, 
dann mach sie zuerst richtig:

Wer eine Funktion schreibt, die einen Buffer befüllt und in der 
Argumentliste nicht die Buffergröße übergibt (und natürlich auch in der 
Funktion überprüft, ob der Buffer nicht überlaufen wird), der sollte 
sofort 30 Schläge mit dem nassen Fetzen auf seinen Hinterkopf bekommen.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Wer eine Funktion schreibt, die einen Buffer befüllt und in der
> Argumentliste nicht die Buffergröße übergibt (und natürlich auch in der
> Funktion überprüft, ob der Buffer nicht überlaufen wird), der sollte
> sofort 30 Schläge mit dem nassen Fetzen auf seinen Hinterkopf bekommen.

Hihi, was nämlich passieren kann ist genau das, was du gerade hattest: 
Merkwürdige Fehler.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.