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


von Gast (Gast)


Lesenswert?

Hallo!

ich habe eine Funktion geschrieben um NMEA-Daten zu parsen. Die Funktion 
wird mit
1
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.

1
typedef struct navstruct
2
{
3
  int newdata;
4
  double time;
5
} navstruct;
6
7
void ParseMessage(char *, int, navstruct *);
8
void ParseField(char **, char *);
9
10
int main(void)
11
{
12
  navstruct NavState;
13
  char dispbuff[33];
14
  ...
15
ParseMessage("$GPGGA,190533.920,4806.0000,N,01117.0000,E,1,09,0.9,475.3,M,47.8,M,,0000*5C", GGA, &NavState);
16
  ...
17
  sprintf(dispbuff, "%d %d", NavState.newdata, (int)NavState.time);
18
  lcd_puts(dispbuff);
19
  ...
20
}
21
22
void ParseMessage(char * Message, int NMEA, navstruct * pNavState) {
23
  char * pMessage;
24
  char TempBuff[10]; 
25
26
  pMessage = Message;
27
  ParseField(&pMessage, TempBuff);
28
  pNavState->time = atof(TempBuff);
29
  pNavState->newdata = 1;
30
}

von Thomas D. (t0mmy)


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.

von Gast (Gast)


Lesenswert?

Auch
1
typedef struct navstruct_xy
2
{
3
  int newdata;
4
  double time;
5
} navstruct;
oder
1
typedef struct
2
{
3
  int newdata;
4
  double time;
5
} 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...

von Thomas D. (t0mmy)


Lesenswert?

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

von Gast (Gast)


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.

von Johann L. (gjlayde) Benutzerseite


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?

von Stefan E. (sternst)


Lesenswert?

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

von Thomas D. (t0mmy)


Lesenswert?

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

von Tonne (Gast)


Lesenswert?

1
typedef struct navstruct_xy
2
{
3
  int newdata;
4
  double time;
5
} navstruct;
6
...
7
int main(void)
8
{
9
  navstruct_xy NavState;
10
...
??

von Walter (Gast)


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?

von Tonne (Gast)


Lesenswert?

ups, dort natürlich dann auch:
1
void ParseMessage(char * Message, int NMEA, navstruct_xy * pNavState) {
oder besser gleich
1
typedef struct navstruct
2
{
3
  int newdata;
4
  double time;
5
} ;
6
...
7
int main(void)
8
{
9
  navstruct NavState;
10
...
11
}
12
...
13
void ParseMessage(char * Message, int NMEA, navstruct * pNavState) {
14
...
oder so

mfg

von Tonne (Gast)


Lesenswert?

Müll geschrieben, steht ja schon "typedef" davor, sorry

von Klaus W. (mfgkw)


Lesenswert?

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

von Gast (Gast)


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.

von Gast (Gast)


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:
1
void ParseMessage(char * Message, int NMEA, navstruct * pNavState) {
2
  char * pMessage;
3
  char TempBuff[10]; 
4
5
  pMessage = Message;
6
  ParseField(&pMessage, TempBuff);
7
  pNavState->time = atof(TempBuff);
8
  pNavState->newdata = 1;
9
 
10
 dtostrf(pNavState->time, 6, 3,outbuff); 
11
 uart_puts_P("ParseMessage() ");
12
 uart_puts(outbuff);
13
}
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?

von Klaus W. (mfgkw)


Lesenswert?

welche Zeile?
welches NavStruct?
wo ist der restliche Quelltext?

von Gast (Gast)


Angehängte Dateien:

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.

von Stefan E. (sternst)


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.

von Gast (Gast)


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 :-)

von Karl H. (kbuchegg)


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.

von Simon K. (simon) Benutzerseite


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.

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.