Zu viele Pointer - brauche Hilfe.

Gast #1459360
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
}
Gast #1459377
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...
Gast #1459385
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.
Gast #1459419
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?
Gast #1459473
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
Gast #1459673
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.
Gast #1460593
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?
Gast #1460660
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.
Angehängte Dateien:
Gast #1460951
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 :-)
#1460975
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.
Persönliche Seite #1461397
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren