Forum: Compiler & IDEs Hellsichtige Funktionsausführung?


von Math (Gast)


Lesenswert?

Hallo,
Ich schreibe gerade ein Programm und bin bis jetzt so weit:
1
void setup(){
2
  Serial.begin(9600);
3
  Serial.println("setup"); 
4
}
5
6
void loop(){
7
  Serial.println("loop");
8
  changeNavMode(7);
9
  delay(100);
10
}
11
12
void changeNavMode(int targetMode){
13
  Serial.println("0");
14
15
              //Syncchars   class ID    Len         Mask        Data  
16
              //0xB5  0x62  0x06  0x24  0x24  0x00  0xFF  0xFF
17
  int messageLength = 32;
18
  byte message[] = {0x06, 0x24, 0x24, 0x00, 0x00, 0x01};
19
  Serial.println("1");
20
21
  message[6] = targetMode;
22
  for(int i = 7; i < messageLength + 6; i++){
23
    //fill with 0s
24
    message[i] = byte(0x00);
25
  }
26
  Serial.println("2");
27
28
  
29
  for(int x = 0; x < (sizeof(message) / sizeof(message[0])); x++){
30
    Serial.print(message[x]);
31
    Serial.print(",");
32
  }
33
  Serial.println("ended");
34
35
}
Leider sehe Ich im seriellen Monitor wenn das Programm läuft nur "setup" 
aber nicht "loop". Wenn Ich jetzt aber changeNavMode(7); 
herauskommentiere kommt wie erwartet loop in Dauerschleife. Wie kann es 
sein dass das Serial.println("loop"); von dem darauffolgenden Aufruf 
beeinflusst wird? Ich denke der Fehler liegt am Compiler und nicht mir 
oder?
Ich probiere das ganze mit der Arduino IDE 1.8.2
Danke schonmal!

von Karl M. (Gast)


Lesenswert?

Hallo,

da sollte man sich erstmal ein wenig C Einverleiben!
Das geht so nicht!
1
byte message[] = {0x06, 0x24, 0x24, 0x00, 0x00, 0x01};
2
message[6] = targetMode;
3
for(int i = 7; i < messageLength + 6; i++){
4
  //fill with 0s
5
  message[i] = byte(0x00);
6
}
Wie groß ist message[] ?

von Math (Gast)


Lesenswert?

Danke! Ich hatte da einen Wert, habe ihn aber weil er zu klein war 
weggemacht und habe dann völlig vergessen wieder etwas reinzuschreiben. 
Warum sagt das der Compiler nicht? Und warum stoppt dann sie 
Programmausführung nicht erst an der Stelle? Jetzt habe Ich den 
richtigen Wert reingeschrieben und es geht aber es wäre besser wenn der 
Compiler sowas meldet

von Karl M. (Gast)


Lesenswert?

Hallo,

ich schrieb ja schon, am Anfang steht das Studium der Sprache C bzw. 
C++.

Was ist denn in deinen Augen der "richtige Wert"?

von Math (Gast)


Lesenswert?

Also mein Ziel ist es ein GPS-Modul über das UBX-Protokoll anzusprechen. 
Das Array message wird dann über die Serielle Schnittstelle an das 
GPS-Modul gesendet. Laut Datasheet hat die Nachricht die ich senden will 
eine länge von 38 byte (mit checksum 40). Wie würdest du das denn 
machen? Ich wollte jetzt die Nachrichten-ID hardcoden (das ist wie 
message im code steht) und dann den wert der geändert werden soll 
(targetMode) anhängen, dann den Rest der Nachricht mit Nullen auffüllen 
(Ist ja sowieso maskiert) und dann die Prüfsumme ausrechnen und 
anhängen.

von Bernd K. (prof7bit)


Lesenswert?

Math schrieb:
> Ich denke der Fehler liegt am Compiler und nicht mir
> oder?

Was verleitet Dich zu solch maßloser Selbstüberschätzung? 400 Jahre 
Erfahrung in C?

von Math (Gast)


Lesenswert?

Naja so im Nachhinein finde ich es schon schwach vom Compiler dass so 
ein Fehler nicht angezeigt wird und das Programm einfach einfriert

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Derartige Fehler zu finden ist nicht Aufgabe des Compilers. Das kann man 
mit anderen Analysewerkzeugen wie valgrind oder cppcheck anstellen.

cppcheck ist auch für Windows verfügbar und dürfte zu Deinem Code 
einiges anzumerken haben.

http://cppcheck.sourceforge.net/

von Jobst Q. (joquis)


Lesenswert?

Math schrieb:
> aber nicht "loop". Wenn Ich jetzt aber changeNavMode(7);
> herauskommentiere kommt wie erwartet loop in Dauerschleife.

Das erste "loop" hängt wohl noch in einem Zwischenspeicher, da die 
Herausgabe Zeit beansprucht. Dann hängt sich das Programm wegen dem 
changeNavMode-Murks auf und nichts mehr tut sich.

von Math (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> cppcheck ist auch für Windows verfügbar und dürfte zu Deinem Code
> einiges anzumerken haben.

Komisch, irgendwie sagt es gerade "Keine Fehler gefunden" (Ich habe die 
.ino datei zu einer .cpp -Datei umbenannt und gescannt).

Jobst Q. schrieb:
> changeNavMode-Murks

Was soll Ich denn ändern? Mir fällt kein eleganterer Weg ein.

von Jobst Q. (joquis)


Lesenswert?

Math schrieb:
> Rufus Τ. F. schrieb:
>> cppcheck ist auch für Windows verfügbar und dürfte zu Deinem Code
>> einiges anzumerken haben.
>
> Komisch, irgendwie sagt es gerade "Keine Fehler gefunden" (Ich habe die
> .ino datei zu einer .cpp -Datei umbenannt und gescannt).
>
> Jobst Q. schrieb:
>> changeNavMode-Murks
>
> Was soll Ich denn ändern? Mir fällt kein eleganterer Weg ein.

Auf jeden Fall muss der Puffer (message) groß genug sein für die 
folgenden Aktionen. Sonst wird der Stack überschrieben und beim return 
ist die Rücksprungadresse nicht mehr da.

Math schrieb:
> Danke! Ich hatte da einen Wert, habe ihn aber weil er zu klein war
> weggemacht und habe dann völlig vergessen wieder etwas reinzuschreiben.
> Warum sagt das der Compiler nicht? Und warum stoppt dann sie
> Programmausführung nicht erst an der Stelle? Jetzt habe Ich den
> richtigen Wert reingeschrieben und es geht aber es wäre besser wenn der
> Compiler sowas meldet

Du hast es also schon erledigt.

von Math (Gast)


Lesenswert?

Jobst Q. schrieb:
> Du hast es also schon erledigt.

Ja, aber es funktioniert immernoch nicht.
Das Programm läuft jetzt und es kommen Daten raus aber das GPS-Modul 
reagiert noch nicht.
Wenn Ich das ganze mit dem Logic Analyzer anschaue sieht es gut aus, nur 
die Prüfsumme habe ich noch nicht nachgerechnet. Ich denke also daran 
liegts... Danke an alle für die Hilfe!

von M.K. B. (mkbit)


Lesenswert?

Math schrieb:
> Komisch, irgendwie sagt es gerade "Keine Fehler gefunden" (Ich habe die
> .ino datei zu einer .cpp -Datei umbenannt und gescannt).

Mit deinem Code oben kommt bei mir in Cppcheck V. 1.83 genau das raus, 
was die anderen hier auch schon erwähnt haben.
- Array 'message[6]' accessed at index 6, which is out of bounds.
- Array 'message[6]' accessed at index 37, which is out of bounds.

Math schrieb:
> Ich denke der Fehler liegt am Compiler und nicht mir
> oder?
Out of range Zugriffe sind undefined behaviour. Der Compiler kann also 
machen, was er will und hat immer recht. Es darf sogar jeder Compiler 
etwas anderes machen.

von Math (Gast)


Lesenswert?

Ja, Ich habe mit cppcheck auch meinen verbesserten Code getestet und da 
sind anscheinend keine Fehler. Ich habe jetzt auch die Nachricht die Das 
PC-Programm an das Modul sendet 1zu1 kopiert und es funktioniert, jetzt 
probiere ich mal nach und nach die variablen einzuführen. Das der Code 
nicht nacheinander abgegangen wird wusste ich aber nicht. Ich dachte 
wenn es ein Pronlem gibt wird zuerst der Code bis zum Fehler ausgeführt 
und dann passiert etwas unerwartetes. Danke nochmal, ihr habt mir echt 
geholfen!

von Jobst Q. (joquis)


Lesenswert?

Math schrieb:
> Das der Code
> nicht nacheinander abgegangen wird wusste ich aber nicht.

Der Code wird schon nacheinander abgegangen. Der Code ist aber viel 
schneller als die serielle Schnittstelle.

Serial.println() wartet wohl nicht bis der Text am anderen Ende 
vollständig angekommen ist, sondern speichert ihn in einem FIFO-Puffer, 
aus dem er dann relativ langsam Bit für Bit gesendet wird.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Math schrieb:
> Ja, Ich habe mit cppcheck auch meinen verbesserten Code getestet und da
> sind anscheinend keine Fehler.

Zeigen bitte. Alles andere ist Spekulation.

Man kann mit Leichtigkeit in C Bufferoverflows erzeugen, die von keiner 
Maschine der Welt durch Quelltextanalyse erkannt werden - erst zur 
Laufzeit, wenn es knallt.

Simples Beispiel:

Zugriff über einen Index auf ein Array, wobei der Index erst zur 
Laufzeit bekannt wird, z.B. wenn er über die aktuelle Zimmertemperatur 
ausgerechnet wird. Knallt die Sonne mal auf Dein Modul, wunderst Du 
Dich, warum das Programm nicht mehr das macht, was es soll.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Jobst Q. schrieb:
> Serial.println() wartet wohl nicht bis der Text am anderen Ende
> vollständig angekommen ist, sondern speichert ihn in einem FIFO-Puffer,
> aus dem er dann relativ langsam Bit für Bit gesendet wird.

Jepp. Dafür gibt es Serial.flush().

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.