Forum: PC-Programmierung Arduino-C++: Typ-Problem, erbitte Hilfe


von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

In den Beispielprogrammen der Netzwerk-Library für nRF24L01-Transmitter 
(https://schullebernd.de/master-slave-netzwerk-mit-nrf24l01-und-arduino-esp8266/) 
taucht folgendes Code-Segment auf, was auch funktioniert:
1
  ...
2
  char* message = "test message.";
3
  Serial.println(message); //<--- das zeigt auch 'test message." an!
4
  nd.sendToDevice(nd.NetworkDevice.MasterMAC, message, strlen(message) + 1);
5
  ...

Nun benötige ich aber für message einen variablen String und habe mich 
mit der Typumwandung herumgequält. Der folgende Code wird zwar ohne 
Fehler compiliert, aber Serial.println(message) ist leer und auch das 
was gesendet wird. Der Empfänger stellt zwar fest, es wurde etwas 
gesendet, aber auch dort ist die Ausgabe in den seriellen Monitor leer 
...
1
  ...
2
  String mystr = "test message.";
3
  char* message;
4
  mystr.toCharArray(message, mystr.length());
5
  Serial.println(message); //<--- das gibt eine leere Zeile
6
  nd.sendToDevice(nd.NetworkDevice.MasterMAC, message, strlen(message) + 1);
7
  ...

Die Anzahl der gesendeten Zeichen wird vom Empfänger richtig erkannt, 
nur die Sendung selbst ist quasi unsichtbar und belegt im seriellen 
Monitor die Länge null. Code auf Empfängerseite:
1
  ...
2
  int messageSize = networkDevice.available();
3
  if (messageSize > 0)
4
  {
5
    Serial.print("receive: ");
6
    Serial.print((char*)networkDevice.getMessage());
7
    Serial.print(" - ");
8
    Serial.println(messageSize);
9
  }
10
  ...

Kann mir bitte mal jemand zeigen, wie es richtig geht? Ist bestimmt nur 
eine Kleinigkeit. Danke.

: Bearbeitet durch User
von o.O (Gast)


Lesenswert?

Seit wann gibt es toCharArry in C++?
Du knnst einfach mystr.c_str() machen um enen zeiger darauf zu 
bekommn...

Wenn du den String erst kopieren möchtest:

char* message = new char[mystr.length()+1]
memcpy(message, mystr.c_str(), mystr.length()+1)

von Wurmi (Gast)


Lesenswert?

Der Buffer muss auch eine Größe haben.
So werden die nachfolgenden Daten im Speicher überschrieben.
1
char message[länge];

oder dynamisch allociert und dann dem Zeiger zugewiesen.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Danke! Die zwei Zeilen von o.O. mit memcpy tun, was sie sollen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Frank E. schrieb:
> Danke! Die zwei Zeilen von o.O. mit memcpy tun, was sie sollen.

Und schon haben wir ein Speicherleck ...

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Wilhelm M. schrieb:
> Frank E. schrieb:
>> Danke! Die zwei Zeilen von o.O. mit memcpy tun, was sie sollen.
>
> Und schon haben wir ein Speicherleck ...

Ja, habe ich inzwischen auch gemerkt, läuft nur immer eine zeitlang ...

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

1
 ...
2
    mybuf = "Test " + String(cnt1);
3
    char message[mybuf.length()+1];
4
    memcpy(message, mybuf.c_str(),mybuf.length()+1);
5
 ...

das tut aber jetzt!

von Wilhelm M. (wimalopaan)


Lesenswert?

Frank E. schrieb:
> Wilhelm M. schrieb:
>> Frank E. schrieb:
>>> Danke! Die zwei Zeilen von o.O. mit memcpy tun, was sie sollen.
>>
>> Und schon haben wir ein Speicherleck ...
>
> Ja, habe ich inzwischen auch gemerkt, läuft nur immer eine zeitlang ...

Warum willst Du es überhaupt in ein C-Array kopieren?
Weil Du eigentlich snprintf() verwenden willst?

Du kannst das C-Array lokal auf dem Stack allokieren, wenn Dein Stack 
nicht überläuft.
Du kannst es statisch allokieren.
Du kannst es (wie oben) dynamsich allokieren, dann aber wieder löschen.
Du kannst auch std::array oder std::vector nehmen.
Du kannst auch std::unique_ptr<[]> nehmen.

von Wilhelm M. (wimalopaan)


Lesenswert?

Frank E. schrieb:
>
1
>  ...
2
>     mybuf = "Test " + String(cnt1);
3
>     char message[mybuf.length()+1];
4
>     memcpy(message, mybuf.c_str(),mybuf.length()+1);
5
>  ...
6
>
>
> das tut aber jetzt!

Klaro.
Ich hoffe, Du verstehst den Unterschied. Falls nicht, kauf die ein 
C-Buck, besser eines über C++ !

P.S.: Willst Du tatsächlich das Sentinel mit senden?

von DerEgon (Gast)


Lesenswert?

Und was spricht dagegen, den einfachsten Ansatz zu wählen?
1
String mystr = "test message.";
2
3
nd.sendToDevice(nd.NetworkDevice.MasterMAC, mystr.c_str(), mystr.length() + 1);

von EAF (Gast)


Lesenswert?

DerEgon schrieb:
> Und was spricht dagegen, den einfachsten Ansatz zu wählen?

Der einfache Ansatz ist zu einfach.
Zu zuverlässig.
Und viel zu wenig beeindruckend.

von o.O (Gast)


Lesenswert?

Frank E. schrieb:
> Wilhelm M. schrieb:
>> Frank E. schrieb:
>>> Danke! Die zwei Zeilen von o.O. mit memcpy tun, was sie sollen.
>>
>> Und schon haben wir ein Speicherleck ...
>
> Ja, habe ich inzwischen auch gemerkt, läuft nur immer eine zeitlang ...

musst natürlich mit free den Speicher wieder freigeben...
free(message)

Aber ja unnötig ist das ganze.

von Wilhelm M. (wimalopaan)


Lesenswert?

o.O schrieb:
> Frank E. schrieb:
>> Wilhelm M. schrieb:
>>> Frank E. schrieb:
>>>> Danke! Die zwei Zeilen von o.O. mit memcpy tun, was sie sollen.
>>>
>>> Und schon haben wir ein Speicherleck ...
>>
>> Ja, habe ich inzwischen auch gemerkt, läuft nur immer eine zeitlang ...
>
> musst natürlich mit free den Speicher wieder freigeben...
> free(message)

malloc/calloc/realloc -> free
new -> delete

Aber das ist alles old-school (und so auch nicht exception-safe).
Nimm std::unique_ptr.

: Bearbeitet durch User
von o.O (Gast)


Lesenswert?

Wilhelm M. schrieb:
> malloc/calloc/realloc -> free
> new -> delete
>
> Aber das ist alles old-school (und so auch nicht exception-safe).
> Nimm std::unique_ptr.

stimmt! Ich bin C C++ verseucht

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.