Moin Forum, so, nachdem ich jetzt zwei Abende vergeblich geknobelt habe und zu keinem Ergebnis komme, möchte ich euch an meinem (wahrscheinlich ist es gar keins) Problem teilhaben lassen. Ich übergebe aus der Funktion ReadData einen Zeiger auf ein Array aus unsigned chars. Diesen Zeiger versuche ich dann in der Funktion OnPollTimer zu dereferenzieren, um die empfangenen Characters weiterzuverarbeiten. Das Auslesen in ReadData funktioniert, Buffer hat den richtigen Inhalt. Aber das Dereferenzieren in OnPollTimer bringt nur Grütze zustande. Sieht jemand von euch, was ich da falsch mache? Besten Dank! Gruß, Rüdiger
Ha! zu so später Stunde kann ich sogar mit meinen leicht verstaubten C++-Kenntnissen noch punkten (hoff ich zumindest). Du erzeugst in ReadData() den Puffer auf dem Stack und gibst dann den Zeiger darauf zurück. Nachdem die Funktion wieder verlassen wird, ist der Zeiger nicht mehr gültig. Du musst den Puffer mit new auf dem Heap erzeugen und (unter Umständen wichtig) mit delete wieder löschen, wenn Du ihn nicht mehr brauchst (sonst hast Du schon ein Memory Leak). Alternativ eine Ebene höher deklarieren, z.B. global. HTH
Stimmt genau. Nie nie nie und nimmer Zeiger auf lokale Variablen aus einer Funktion zurückgeben. Das ist in c(++) eine absolute Todsünde ;)
Ja, das ist das Problem. Der Buffer ist lokal in der Funkton definiert. Sobald die Funktion verlassen wird, existiert er nicht mehr.
Vielen Dank für die schnellen Antworten, aber es funzt leider immer noch nicht. Ich habe nun einen globalen Zeiger namens PointerToReadBuffer deklariert. Die Funktion ReadData gibt jetzt keinen Zeiger mehr zurück, sondern kopiert die Adresse des ersten Array-Elements auf diesen globalen Zeiger. Die Funktion OnPollTimer klappt jetzt in der ersten Variante wunderbar, aber nicht in der Variante zwei. Sobald die for-Schleife betreten wird und das erste Mal die Funktion IntToStr aufgerufen wird, zeigt der PointerToReadBuffer wieder nur auf Murks... Warum das so ist, kann ich mir leider nicht erklären. Habt ihr da noch Vorschläge? Gruß, Rüdiger
Also nochmal: Du darfst den Puffer nicht lokal erzeugen! Wie Du den Zeiger zurückgibst ist vollkommen egal. Der Puffer muss global (unschön) oder mit new (besser aber schwieriger -> Memory Leak) erzeugt werden.
Der Fehler ist immer noch in ReadData. Du hast immer noch einen Zeiger auf eine lokale Variable. Ob du den pointer als Rückgabewert hast oder als globale Variable übergibt ist egal. Das entscheidene ist, wo sich der Speicherplatz befindet, auf den der Zeiger zeigt. Und das ist immer noch lokal in der ReadData. Du solltest entweder im Hauptprogramm keinen Pointer, sondern den Buffer anlegen (global z.B unsignec char Buffer[128], und keinen lokalen Buffer mehr verwenden) oder einen neuen Speicherbereich mittels new in ReadData reservieren und darauf einen Pointer zurückgeben. Nach verwendung im Hauptprogramm dann mit delete löschen. Version 1: .. unsigned char gBuffer[128]; void ReadData(..) { ft_read(... ,Buffer,... ) ..} Version 2: unsigned char* ReadData(..) { unsigned char*buffer=new unsigned char[128]; ft_read(..., buffer, ...) return buffer; } OnPolltimer { unsigned char*buffer = readData() ... buffer benutzen delete[] buffer;
Um es nochmal ganz klar und eindeutig zu sagen: Lokale Variablen existieren nicht mehr, nachdem eine Funktion verlassen wurde. Hast du also eien Funktion: void foo() { unsigned char Buffer[20]; ... } dann wird die Variable Buffer nach verlassen der Funktion wieder in Luft aufgelöst. Es gibt sie einfach nicht mehr. Daran ändert sich auch nichts, wenn es einen Pointer auf diese Variable gibt. Der Pointer zeigt dann ins Nirwana aber nicht mehr auf die Variable 'Buffer'. Denn die gibt es ja nicht mehr. Wenn dein Aufrufer Zugang zu diesem Buffer braucht, dann ist die einfachste Variante die, dass der Aufrufer den Buffer zur Verfügung stellt: void foo( char* Buffer, int BufferLen ) { // foo schreibt was in den Buffer // ausserdem ist es immer gut, wenn man, wie in diesem // Fall dem foo() auch mitteilt wie gross den das // übergebene Array tatsächlich ist. Dann kann foo() // dafür sorgen, dass nichts zerstört wird if( BufferLen > 2 ) { Buffer[0] = 'a'; Buffer[1] = 'b'; Buffer[2] = '\0'; } } void bar() { char Buffer[20]; foo( Buffer, sizeof( Buffer ) ); ... Hier kann dann bar() mit den Werten arbeiten, die ... foo im Buffer hinterlassen hat }
Hey klasse, es funktioniert! Danke an alle, insbesondere für die verständlichen Erklärungen. Grr, in Ada erscheint mir das Zeigerkonzept aus sich heraus irgendwie schlüssiger zu sein. Insofern noch eine Verständnisfrage zur Version 2 von Tobi (die jetzt so auch bei mir läuft): Buffer ist ein Zeiger auf einen unsigned char. Dieser Zeiger zeigt auf den Anfang eines Speicherbereiches, der Platz für 128 unsigned chars bietet. Die Funktion ftRead möchte ja nun dieses Array übergeben bekommen, um darin etwas speichern zu können. Eine Derefenzierung mittels "ft_read(..., *buffer, ...)" macht keinen Sinn, da dies ja nur den Inhalt der ersten Speicherzelle darstellt. Unabhängig davon ob Buffer nun gemäß "unsigned char Buffer[128]" oder aber nach "unsigned char*buffer=new unsigned char[128]" definiert ist, ist der Aufruf von "ft_read(..., buffer, ...)" gültig. Warum ist das so? Gruß, RÜdiger
Meinst du, weil im einen Fall der Buffer ein Array ist, im anderen Fall ein Zeiger? In vielen Fällen "zerfällt" ein Array in einen Zeiger auf sein erstes Element. Daher kann man oft (aber nicht immer) ein Array wie einen Zeiger nutzen. Ein Funktionsaufruf ist ein Fall, in dem bei Übergabe eines Array immer automatisch ein Zeiger auf das erste Element des Arrays in der Funktion ankommt.
Hinter dem Namen des Arrays verbirgt sich nichts anderes als ein Zeiger auf das erste Element. Wie Du die Dereferenzierung vornimmst ist vollkommen egal. Buffer[0] ist identisch zu *Buffer, genauso wie Buffer[n] identisch zu *(Buffer+n) ist. Man kann das beliebig mischen: char * Buffer = new char[128]; ... Buffer[123] = 16; oder auch char Buffer[128]; ... *(Buffer+12) = 'c';
kurzer Nachtrag: Wenn Du mit new Speicher vom Heap anforderst, ist es zwingend erforderlich, dass Du diesen wieder freigibst. Macht sich bei Deinem Problem vielleicht noch nicht bemerkbar, aber irgendwann wird es das. Also den Speicher unbedingt wieder mit delete [] Buffer; freigeben! Natürlich erst, wenn Du ihn nicht mehr brauchst.
So erstmal sorry für die späte Antwort. @Magnus: Ja, genau das meinte ich. Für mich ist das unrund, wie gesagt in Ada ist ein Zeiger ein Zeiger und ein Array ist ein Array. Und ein Zeiger auf ein Array ist etwas ganz anderes als das Array selbst. @Frank: Vielen Dank! Gruß, Rüdiger
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.