Guten Abend, Ich habe ein kleines Problem mit meiner Software. Ich hatte letztes Jahr(So um Oktober) mal ein Thema hier wo es um mein Aquarium Steuergerät ging wo mir der Platz aus ging. Da ich mich ja dafür entschlossen habe den gesamten Programmcode neu zu schrieben anstatt im bestehen Projekt zu überarbeiten, habe ich dieses Stück für Stück getan. Es wurde mir ja mehrmals geraten das ich die String nicht mehr im RAM ablegen soll sondern mit den "_P" Funktion und PSTR sowie PROGMEM in den Flash auslagere. Das habe ich auch immer bis jetzt getan(Außer Serielle Nachrichten die nur zur Temporären Überprüfung waren wurden ohne _P und PSTR verwendet). Nur jetzt habe ich ein Problem und zwar bin ich gerade an dem Menüfunktion Netzwerk angelangt, und dort verwende ich ein Switch Case. In diesem Switch Case lade ich einen String "preIpStr" mit strcpy_P vor. Dort steht dann zB. drin "IP" oder "GW". Das Problem liegt am zweiten strcpy_P in case Fall 2 wenn ich das drin stehen habe und die IP-Adressen im Menü ändern möchte wird mein TFT Display(ili9341) mit allen möglich Zeichen ausgefüllt und der Controller hängt sich komplett auf. Nach 4 Sekunden setzt dann der Watchdog Timer den Controller zurück. Wenn ich aus dem strcpy_P die normale Version mache strcpy funktioniert der Programmcode Problemlos. Kann mir nicht erklären woran das liegt, char Array ist groß genug teiweise auch mal auf 100 Bytes erhöht ändert aber nix. Wenn ich das strcpy_P aus dem Case Fall 1 entnehme(Also strcpy_P(preIpStr, PSTR("IP"));) und im Case Fall 2 es stehen lasse(strcpy_P(preIpStr, PSTR("GW"));) dann funktioniert der Code wieder. Gibt es eine Limitierung bei PSTR/pgmspace? Der RAM ist noch nicht Ansatz weiße voll. Flash aktuell: 41,8kB 32 % RAM aktuell : 2,59kB 15 % Ich habe die Funktion mal angehängt. Sie ist zum Teil kommentiert. Kann mir da jemand weiter helfen? Mfg
Beitrag #6168114 wurde vom Autor gelöscht.
Felix N. schrieb: > Es wurde mir ja mehrmals geraten das ich die String nicht mehr im RAM > ablegen soll sondern mit den "_P" Funktion und PSTR sowie PROGMEM in den > Flash auslagere. richtig so, nur die strings standen auch schon vorher im flash und sind nur extra zum init ins ram kopiert worden. Felix N. schrieb: > Das Problem liegt am zweiten > strcpy_P glaube ich nicht, weil da sieht alles ok aus. ich denke an bereichsüberschreitung/-schreibung ... mache debug ausgaben von dem code davor! bzw. verwende as7 und den simulator um dir codebereiche anzuschauen! mt
Wo wird denn 'ipByteSelector' initialisiert? Du greifst da mit ...-1 drauf zu. Wenn der aber 0 ist, gibt's ein Problem
Apollo M. schrieb: > richtig so, nur die strings standen auch schon vorher im flash und sind > nur extra zum init ins ram kopiert worden. Ach ja, so war das. Apollo M. schrieb: > glaube ich nicht, weil da sieht alles ok aus. ich denke an > bereichsüberschreitung/-schreibung ... Ah ok. Apollo M. schrieb: > mache debug ausgaben von dem code davor! > bzw. verwende as7 und den simulator um dir codebereiche anzuschauen! Also mit dem Simulator habe ich das wohl schon mal versucht jedoch komme ich da noch nicht wie man den richtig anwendet. Muss da nochmal schauen zu mal die Funktion ja nur ausgeführt wird denn ein Knopf gedrückt wird und ein bestimmter Wert auf 1 gesetzt wird sonst wird die Funktion ja garnicht ausgeführt. Von was soll ich den genau debug ausgaben machen? Von den Strings? Pit S. schrieb: > Wo wird denn 'ipByteSelector' initialisiert? ipByteSelector ist eine globale uint8_t Variable und wird mit dem Wert 0 initialisiert. Pit S. schrieb: > Du greifst da mit ...-1 > drauf zu. Huch, wo greife ich den da mit -1 drauf zu? //Edit: Meinst du bei eIP[ipByteSelector - 1]? Mfg
:
Bearbeitet durch User
Apollo M. schrieb: > glaube ich nicht, weil da sieht alles ok aus. ich denke an > bereichsüberschreitung/-schreibung ... Hallo nochmal, Ich habe nochmal ein bisschen geschaut also Debug Nachrichten auszugeben macht kein Sinn da solange das zweite strcpy_P drin steht da keine Debug Nachrichten mehr an den UART gesendet werden sobald die Funktion aufgerufen wird auch wenn die Sendung der Nachrichten vor dem strcpy_P erfolgt. Komisch ist ja das der Programmcode Problemlos funktioniert wenn ich den String in den RAM lade und nicht über PSTR ablege. Auch Ausblenden einzelner Codeteile vor und nach dem strcpy_P nach nix gebracht der Code funktioniert nur wenn das strcpy_P durch strcpy ersetzt wird oder das strcpy_P komplett raus genommen wird. Nochmal zu dem ipByteSelector das ist ja wie schon erwähnt eine globale Variable die mit 0 initialisiert wird. Bevor jedoch die changeIP() Funktion aufgefunden wird(Diese Funktion ist ja nur dafür da die Werte zu ändern) wird eine andere Funktion aufgerufen welche den ipByteSelector zuweist. Beim ersten Knopfdruck wird der Selector auf 1 gesetzt und wählt damit das erste Byte der IP-Adresse aus bei nächsten drücken wird der um 1 erhöht und wählt dann das zweite Byte aus geht alt bis 4 dann wird er zurückgesetzt. Nur kann ich mir das mit dem strcpy_P nicht erklären. Es macht für mich irgendwie kein sinn. mfg
:
Bearbeitet durch User
Guten Abend nochmal an alle, Es hat zwar in der zwischen Zeit keiner geantwortet jedoch habe ich selber noch fleißig weiter gesucht und konnte das Problem teilweise lösen kann es mir aber immer noch nicht erklären warum das so ist. Also was ich mittlerweile feststellen konnte das das Problem wohl nicht an dem zweiten strcpy_P liegt sondern wahrscheinlich an dem:
1 | sprintf_P(strIP, PSTR("%03d"), eIP[ipByteSelector - 1]); //Format String to drawing |
Wenn ich die sprintf_P Zeile auskommentiere funktioniert der Code wieder Problemlos aber gleichzeitig wenn ich die sprintf_P Zeile drin lasse und oben eine der strcpy_P auskommentiere funktioniert der Code auch. Wie kann das??? Also eIP und ipByteSelector sind gültig und auch initialisiert. Daher keine Probleme ipByteSelector hat zum Zeit Punkt den Wert 1 und in eIP[0] steht dann der entsprechen Wert. Ich habe jedoch noch das 03 in dem %d drin damit wenn man eine Zahl unter 100 eingibt das dort nicht 99 steht sondern 099 weil sich sonst die ganze Display Zeile verschiebt und das alles dann nicht mehr richtig funktioniert. Jedoch wenn ich das %03d zu einem einfach %d ersetzt funktioniert der Code Problemlos. Ich kann mir das nicht erklären wieso das so ist. Habt ihr vielleicht eine Idee? Zumal ich die Zeile mit dem sprintf_P schon öfters in Kombination mit %03d bzw. %02d verwendet habe und es gab in der Hinsicht noch nie Probleme. Komisch das ganze ... Mfg
Minimiere doch mal den kompletten Code mit bestehendem Problem als snippet.
Felix N. schrieb: > Jedoch wenn ich das %03d zu einem einfach %d ersetzt funktioniert der > Code Problemlos. Dann ist der Puffer strIP zu klein oder ungültig. Felix N. schrieb: > sprintf_P(strIP, PSTR("%03d"), eIP[ipByteSelector - 1]); "Zeiger/Index - 1" sollte man generell vermeiden. Bei jedem Profi läuten da sofort die Alarmglocken.
gibt es auch ein snprintf_P? Die n Versionen würde ich sowieso
bevorzugen.
> eIP[ipByteSelector - 1]
Da könnte man auch ein ASSERT() Makro für einen Debugbuild verwenden.
Das %03 nicht funktioniert und %3 doch hört sich ja schon nach einem
Grössenproblem an.
Oder du hast dir vorher einen Stackfehler eingefangen, das macht sich
auch gerne erst später bemerkbar.
Hallo an alle, Totomitharry schrieb: > Minimiere doch mal den kompletten Code mit bestehendem Problem als > snippet. Ja das Problem ist ja das dieses Problem sich durch andere Programmzeilen beeinflussen lässt. Daher wird es schwierig. Denn was ich nun herausgefunden habe ist das dort zwischen den strcpy_P und dem sprintf_P noch eine sprintf_P Zeile drin steht:
1 | sprintf_P(strIP, PSTR("%03d"), eIP[ipByteSelector - 2]); |
Auch da ist wieder das Problem das wenn ich das %03d zu einem %3d oder %d der Code wieder funktioniert. Peter D. schrieb: > Dann ist der Puffer strIP zu klein oder ungültig. Hatte ich auch schon dran gedacht jedoch habe ich bereits oben in der Funktion direkt nach den anlegen der Lokalen Variablen versucht die Puffers mit memset() mit 0 zu initialisieren. Jedoch ohne Erfolg. Auch habe ich die Puffergröße von 10 test weiße mal auf 100 Bytes vergrößert aber das Problem tritt dann immer noch auf. Peter D. schrieb: > "Zeiger/Index - 1" sollte man generell vermeiden. Ich kann mir vielleicht vorstellen warum wenn der Index 0 beträgt und ich minus 1 rechne und die Variable vom Typ unsigned ist kann sie ja nicht Negativ werden und es kommt zum Fehler oder? Nur wie soll ich das ganze den anderes machen? Der Index ist nun mal beim Aufruf schon 1 und ich muss es im Index des Arrays 0 speichern alternativ könnte ich den Index 0 vom Array unbelegt lassen dann kann ich ohne das minus 1 auskommen. Ist das die einzige Möglichkeit? Johannes S. schrieb: > gibt es auch ein snprintf_P? Die n Versionen würde ich sowieso > bevorzugen. Ich habe mal kurz geschaut also die Funktion gibt es. Wenn ich die snprintf Funktion richtig verstehe übergibt man als zweites Argument die Größe des Puffers damit die Funktion nicht mehr in den Puffer schreiben kann als der groß ist und somit "Overflows" verhindert werden? Oder warum ist Sie besser? Johannes S. schrieb: > Das %03 nicht funktioniert und %3 doch hört sich ja schon nach einem > Grössenproblem an. Grössenproblem? Ich meine ich brauche ja die führenden Nullen davor damit der Text korrekt auf dem Display anzeigt wird. Arbeite jedoch auch nicht zum ersten mal mit %03d bis jetzt hat das immer Problemlos funktioniert. Scheint irgendwie ein Problem mit den führenden Nullen zu seinen den %3d lässt ja 2 Platz nach linkes ohne es mit nullen aufzufüllen. Was ich aber einfach nicht verstehe warum funktioniert der Programmcode wenn ich ich die normale sprintf Funktion verwende also den String in den RAM lade? Johannes S. schrieb: > Oder du hast dir vorher einen Stackfehler eingefangen, das macht sich > auch gerne erst später bemerkbar. Ok oder auch nicht. Wie kann ich das jetzt ausfinden?
Felix N. schrieb: > Ich kann mir vielleicht vorstellen warum wenn der Index 0 beträgt und > ich minus 1 rechne und die Variable vom Typ unsigned ist kann sie ja > nicht Negativ werden und es kommt zum Fehler oder? da macht dir der Compiler eine implizite Konvertierung und evtl. eine Warnung. Aber das kann man doch einfach blocken wenn am Anfang der Funktion eine Prüfung auf <= 0 mit Ausgabe von Fehlermeldung und return gemacht wird.
Johannes S. schrieb: > da macht dir der Compiler eine implizite Konvertierung und evtl. eine > Warnung. Aber das kann man doch einfach blocken wenn am Anfang der > Funktion eine Prüfung auf <= 0 mit Ausgabe von Fehlermeldung und return > gemacht wird. Hallo, Achso du meinst das der Compiler dann aus dem uint8_t einfach ein int8_t macht? Meinst du dann sowas?:
1 | if(ipByteSelector <= 0) { |
2 | return; |
3 | } |
4 | |
5 | //Sonst sprintf etc... |
Werde ich mir mal im Hinterkopf behalten. Jedoch wenn ich aus der sprintf Funktion die Variable eIP[ipByte... -2] raus nehme und dort fest einfach zB. 50 reinschreibe. Tritt der Fehler ja immer noch auf. Mfg
Felix N. schrieb: > Achso du meinst das der Compiler dann aus dem uint8_t einfach ein int8_t > macht? Nein, der macht daraus ein unsigned int. Was an dem Problem nichts ändert... Oliver
Felix N. schrieb: > Hatte ich auch schon dran gedacht jedoch habe ich bereits oben in der > Funktion direkt nach den anlegen der Lokalen Variablen versucht die > Puffers mit memset() mit 0 zu initialisieren. Jedoch ohne Erfolg. memset kann Deinen Puffer nicht vergrößern, ist hier also sinnlos. Welche Größe hast Du denn memset übergeben? Felix N. schrieb: > Der Index ist nun mal > beim Aufruf schon 1 Warum denn, hast Du irgendwo ein Increment an der falschen Stelle? Wenn es für die Nutzeranzeige ist, dann rechne intern ab 0 und addiere 1 nur für die Anzeige.
Peter D. schrieb: > memset kann Deinen Puffer nicht vergrößern, ist hier also sinnlos. Hi, ja ich weiß das memset die Größe nicht verändern kann aber damit kann ich das Array initialisieren. Damit es nicht NULL ist. Im Moment hat der Puffer strIP eine Größe von 100 Bytes. Peter D. schrieb: > Welche Größe hast Du denn memset übergeben? So habe ich es gemacht:
1 | char strIP[10]; |
2 | |
3 | memset(strIP, 0x00, sizeof(strIP)); |
Peter D. schrieb: > Warum denn, hast Du irgendwo ein Increment an der falschen Stelle? > Wenn es für die Nutzeranzeige ist, dann rechne intern ab 0 und addiere 1 > nur für die Anzeige. Ja sorry, ich habe mir den Teil mit dem ipByteSelector angesehen ich kann auch mit 0 anfangen warum ich da jetzt 1 genommen habe weiß ich nicht mehr jedoch ist das nur ein Index im Code er wird also nie auf der Anzeige erscheinen. Er ist nur dafür die Bytes in der IP-Adresse auszuwählen da eine IPv4 Adresse 4 Bytes hat habe ich wahrscheinlich 1 = 1 Bytes, 2 = 2 Bytes etc... genommen. Das werde ich dann auf 0 abändern also 0 = 1 Bytes etc... Jedoch muss ich an einer Stelle immer noch -1 rechnen. Denn ich habe ja immer noch die Abfrage drin wo geprüft wird ob der ipByteSelector größer als 1 ist und wenn ja wird das vorherige Byte auf dem Display weiß dargestellt und das neue Byte welches jetzt ausgewählt ist zum bearbeiten in Rot. Da muss ich ja dann -1 rechnen um den vorherigen Wert zu bekommen. Oder wie soll ich das da machen?
1 | if(ipByteSelector > 1) { |
2 | ili9341_fillrect((x - 49), (y - 1), clrWidth, clrHeight, BLACK); |
3 | snprintf_P(strIP, sizeof(strIP), PSTR("%03d"), eIP[ipByteSelector - 1]); |
4 | ili9341_combo((x - 49), y, WHITE, BLACK, 2, 3, 0, 0, strIP); |
5 | } |
Es wird dort ja erst geprüft ob der Selector größer als 1 ist(Später dann größer als 0 wenn ich es geändert habe). Wenn es so ist wird mit fillrect der Bereich wo die Zahl steht(zB. 192) mit einem schwarzen Kästchen überlagern damit die Zahlen sich nicht überlappen. Dann wird mit snprintf_P der vorherige Wert entsprechend Formatiert mit führenden Nullen. Und ili9341_combo ist eine Funktion die alles vereinigt also Koordinaten setzten, Text/Hintergrundfarbe wählen, Schriftgröße etc... und dann wird der vorherige Wert in Weiß wieder angezeigt. Der Teil muss doch eigentlich Safe sein oder nicht? Weil ich prüfe doch vorher ob ich den Selector - 1 nehmen darf durch die if Abfrage. Aber es scheint irgend ein Problem mit den führenden Nullen zu seinen, denn ich habe noch was raus gefunden den in einer anderen Funktion die das Menü "malt" habe ich folgende Programmzeile drin:
1 | sprintf_P(strBuffer, PSTR("IP : %d.%d.%d.%d"), MyIP[0], MyIP[1], MyIP[2], MyIP[3]); |
2 | ili9341_combo(4, 77, WHITE, BLACK, 2, 3, 0, 0, strBuffer); |
Sie stellt die Server IP Adresse im Menü da. strBuffer ist ein Puffer mit einer Größe von 400 Bytes und in der main.h angelegt ist der String Puffer für alles(Debug, Menüs malen etc...) Wenn ich dort das erste %d durch ein %03d ersetzte passiert noch nix ersetze ich das zweite %d auch durch ein %03d so das ich dort "%03d.%03d.%d.%d" stehen habe. Und das Menü aufrufe hängt sich der Prozessor wieder auf sobald der das Menü darstellen will. Mache ich aber wieder nur %3d bei allen 4 funktioniert es wieder Problemlos nur halt ohne führenden Nullen dafür dann mit entsprechend vielen Leerzeichen dazwischen. Mfg
Also bei mir funktioniert allein das nicht: Vielleicht hab ich ja etwas übersehen
1 | char strIP[10]; |
2 | char strBuffer[100]; |
3 | int MyIP[4] = {111, 111, 111, 111}; |
4 | void setup() { |
5 | // put your setup code here, to run once:
|
6 | memset(strIP, 0x00, sizeof(strIP)); |
7 | Serial.begin(115200); |
8 | }
|
9 | |
10 | void loop() { |
11 | // put your main code here, to run repeatedly:
|
12 | sprintf_P(strBuffer, PSTR("IP : %d03.%d03.%d.%d"), MyIP[0], MyIP[1], MyIP[2], MyIP[3]); |
13 | Serial.println(strBuffer); |
14 | }
|
Hallo Philipp, Philipp K. schrieb: > %d03.%d03 Du hast %d03 geschrieben. Versuchs mal mit %03d also 03 vor dem d. Bei mir funktioniert das ganze schon. Aber halt nur mit der sprintf Funktion ohne das _P am Ende. Kann es ein das du die Arduino IDE nutzt? Ich weiß jetzt nicht sicher ob es die "_P" Funktion in der Arduino gibt. Mfg
Ups, ja mein Fail. Reproduziere das doch mal selbst in einem gekürzten Code. Ersetzte mal das sprintf durch eine Zuweisung des eigentlichen Ergebnisses.. um Pufferüberläufe zu testen. Edit: wieviel stellen sind in den String Arrays reserviert? Kann man mit den schnippeln nur schätzen. Muss einer mehr für den Abschluss sein. Eine IP bräuchte 17 arrayelemente
:
Bearbeitet durch User
Philipp K. schrieb: > Ups, ja mein Fail. Hallo, Ich scheine wohl erstmal den Fehler gefunden zu haben. Ich habe gerade einfach mal die changeIP() Funktion komplett ausgeblendet so das diese nicht mehr aufgerufen wird. Es gibt aber noch eine andere Funktion die nennt sich editIPs() diese wird als erstes aufgerufen wenn man die IP-Adressen bearbeiten möchte und markiert dann entsprechend den Namen der IP-Adresse in Rot so das man weiß welche man ausgewählt hat. Nachdem nur noch die editIPs() Funktion drin war und der Fehler immer noch aufgetreten ist, also das sich der Controller aufhängt habe ich diese Funktion auch mal ausgeblendet so das sie nicht mehr aufgerufen wird. Danach hängt sich der Controller nicht mehr auf. Also habe ich mir den Code nochmal genauer angeschaut. Dort habe ich auch zwei lokale char Arrays einmal ipStr und preIpStr beide mit einer Größe von 10 Bytes. Die Variable ipStr ist für die ausgewählte IP-Adresse und preIpStr für die vorherige Adresse. Da aber nicht immer eine vorherige Adresse vorhanden ist musste ich das zweite Array dennoch belegen und zwar habe ich das so gemacht:
1 | strcpy_P(preIpStr, NULL); |
Habe jetzt test weiße das ganze durch folgendes ersetzt:
1 | strcpy_P(preIpStr, PSTR("")); |
Habe nämlich die Vermutung das das "NULL" daran schuld gewesen sein könnte. Denn jetzt funktioniert der gesamte Code Problemlos. Warum aber der Code teilweise funktioniert wenn man in einer anderen Funktion was geändert hat. Keine Ahnung. Werde es jetzt mal testen und weiter programmieren ob dieser Fehler wirklich weg bleibt. Ich habe mal meine ethernetMenu.c Datei angehängt. Mfg
Was wird strcpy_P(preIpStr, NULL); Auf einem AVR wohl machen? Es kopiert den Anfang des Flash bis zur ersten gefundenen '\0'. Und das kann ein paar Bytes dauern, wenn die zig Int-Vectoren mit "JMP Badint" vorgelegt sind. Besser eine (falls verfügbar) "n"-Variante der Str-Routine benutzen.
:
Bearbeitet durch User
Carl D. schrieb: > Es kopiert den Anfang des Flash bis zur ersten gefundenen '\0'. Hallo Carl, Das heißt wenn ich strcpy_P mit NULL als zweites Argument übergebe kopiert er alles in den Puffer rein bis er ein \0 gefunden hat? Bedeutet also zb. Wenn es von Flash Adresse 0x00 bis zum zB. 0xFF alles kopiert weil 0xFF ein \0 beinhaltet? Und da der Puffer nicht groß genug ist stürzt er dann ab? Richtig so? Carl D. schrieb: > Besser eine (falls verfügbar) "n"-Variante der Str-Routine benutzen. Ja es gibt eine strncpy_P Variante die will Quelle, Ziel und Größe als Argumente haben. Quelle und Ziele ist ja klar und als Größe kann ich dann einfach mit sizeof und dann die Größe des Puffers übergeben? Also kann ich besser die "n" Funktion verwenden weil wenn er mehr Daten kopiert/schiebt etc... die Funktion einfach aufhört wenn das Limit was als dritte Argument übergeben wird überschritten wird? Oder steht dann nur das bis zum Limit in Puffer? Mfg
Felix N. schrieb: > Carl D. schrieb: >> Es kopiert den Anfang des Flash bis zur ersten gefundenen '\0'. > > Hallo Carl, > > Das heißt wenn ich strcpy_P mit NULL als zweites Argument übergebe > kopiert er alles in den Puffer rein bis er ein \0 gefunden hat? Bedeutet > also zb. Wenn es von Flash Adresse 0x00 bis zum zB. 0xFF alles kopiert > weil 0xFF ein \0 beinhaltet? > > Und da der Puffer nicht groß genug ist stürzt er dann ab? Richtig so? Genau! NULL aka 0 ist eine gültige Flash-Adresse. NULL als "nix" anzusehen ist eine Vereinbarung (die auf mancher HW/manchen OS durchgesetzt wird, aber auf AVR eben nicht). Denn Flash(0) beinhaltet (das erste Byte) eines Sprungs zu "Start"-Routine. Was Konventions ist, daß GCC/AVRLibc die Int-Vektoren zumindest mit einen Sprung zu BadInt() füllen. Das können 0-Bytes vorkommen, oder meist eben auch nicht. Danach kommen dann (falls C++) Adressen der Initialisierungsroutinen für globale Objekte. Dann eventuell benutzte PROGMEN Strings. Letztere würden die Kopierwut von strcpy_P() bremsen, aber da ist es sicher schon zu spät. > Carl D. schrieb: >> Besser eine (falls verfügbar) "n"-Variante der Str-Routine benutzen. > > Ja es gibt eine strncpy_P Variante die will Quelle, Ziel und Größe als > Argumente haben. Quelle und Ziele ist ja klar und als Größe kann ich > dann einfach mit sizeof und dann die Größe des Puffers übergeben? > > Also kann ich besser die "n" Funktion verwenden weil wenn er mehr Daten > kopiert/schiebt etc... die Funktion einfach aufhört wenn das Limit was > als dritte Argument übergeben wird überschritten wird? Oder steht dann > nur das bis zum Limit in Puffer? > > Mfg Die Funktion kennt vom Ziel nur die Adresse, die Länge muß zusätzlich mitgegeben werden, andernfalls kommt die Länge aus der Quelle, und zwar nach der C-String-Konvention "endet mit '\0'".
:
Bearbeitet durch User
Felix N. schrieb: > strcpy_P(preIpStr, NULL); Das ist natürlich ganz großer Mist. NULL nimmt man, um einen Pointer als ungültig zu kennzeichnen, d.h. mit einem solchen Pointer dürfen auf keinen Fall irgendwelche Aktionen erfolgen. Erlaubt ist nur, einen solchen Pointer auf NULL zu testen oder ihm eine gültige Adresse zuzuweisen. Z.B. malloc liefert NULL, wenn kein Speicher belegt werden konnte.
Carl D. schrieb: > > NULL aka 0 ist eine gültige Flash-Adresse. NULL als "nix" anzusehen ist > eine Vereinbarung (die auf mancher HW/manchen OS durchgesetzt wird, aber > auf AVR eben nicht). Ist aber völlig egal, die Verwendung von NULL als *src ist schlicht falsch, und führt zum Fehler. Oliver
Carl D. schrieb: > NULL aka 0 ist eine gültige Flash-Adresse. Nur stehen dort keine Strings, sondern Befehle. D.h. man könnte höchstens dahin springen, um einen SW-Reset zu bewirken.
Carl D. schrieb: > Genau! Oliver S. schrieb: > ist schlicht > falsch, und führt zum Fehler. Hallo nochmal, Ach ja selbst eingebaute Fehler sind ja eh die besten :) Peter D. schrieb: > Nur stehen dort keine Strings, sondern Befehle. Eine Frage bleibt mir da noch. Wenn strcpy im Flash an der Adresse 0 angefangen hat und bis zu einem \0 gesucht hat aber am Anfang nur Befehle stehen wieso kann es dann sein das wenn ich teilweise String Funktion ohne _P verwende ohne andere String Funktion ausblende das der Programmcode trotzdem funktioniert? Peter D. schrieb: > NULL nimmt man, um einen Pointer als ungültig zu kennzeichnen Ach so ok. Ich dachte das wenn ich als weites Argument NULL übergebe das er in den String dann einfach auf 0 setzt. Da lag ich wohl daneben. Immerhin etwas neues dazu gelernt :) Also ich habe meine Funktion nun fast vervollständigt es fehlt jetzt nur noch der Teil mit dem Server Port dann ist sie fertig. Bis jetzt trat der Fehler nicht mehr auf. Ich denke mal das es dann wirklich nur an dem NULL lag. Möchte mich auf jeden Fall bei allen die mir hierbei geholfen haben Bedanken! Vielen Dank an euch! Mfg
Felix N. schrieb: > wieso kann es dann sein das wenn ich teilweise String > Funktion ohne _P verwende ohne andere String Funktion ausblende das der > Programmcode trotzdem funktioniert? Weil an RAM-Adresse 0 das Register r0 gemappt ist, und das wird vom gcc dauerhaft auf den Wert 0 gesetzt. Oliver
Für alle die das vielleicht falsch verstanden haben könnten: Ich hab beschrieben, was konkret auf der HW passiert und nicht zum Ausdruck bringen wollen, daß was der TO "codiert" hat richtig wäre. Offensichtlich ist es falsch, denn es führt zum Chaos. Den Weg dorthin wollte ich ihm erklären.
Felix N. schrieb: > Peter D. schrieb: >> NULL nimmt man, um einen Pointer als ungültig zu kennzeichnen > > Ach so ok. Ich dachte das wenn ich als weites Argument NULL übergebe das > er in den String dann einfach auf 0 setzt. Da lag ich wohl daneben. > Immerhin etwas neues dazu gelernt :) Felix N. schrieb: > Habe jetzt test weiße das ganze durch folgendes ersetzt: > strcpy_P(preIpStr, PSTR("")); Was Du eigentlich willst ist:
1 | *preIpStr = '\0'; |
oder
1 | preIpStr[0] = '\0'; |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.