Zeigerproblem



  • Ts, Ts, Ts ....

    1. Du erzeugst INNERHALB einer Funktion ein Temporaeres Array (Stack)
    2. Du fuellst das mit Werten (Naja)

    3. Wo schreibst Du die Datei? In einer ANDEREN Funktion!!! Oder nicht?
    Wenn ja: Dein Datenfeld ist mit verlassen der Funktion UNGUELTIG. D.h. bei erstbester Gelegenheit werden die Daten da im RAM ueberschrieben!!!

    - Du verlierst den Zeiger auf das Feld - 🕶

    3. qwe.Data=""; erzeugt eine Referenz auf einen String der Laenge Null!!! dhinter ist kein RAM reserviert!
    4. qwe.Data[s] greift damit HINTER Deine (leere) Stringvariable!!!
    Das kann nicht gut gehen!!! 😮



  • Wieso ist das Array temporär? Es wird mit new erzeugt, d.h. dynamisch und müsste doch auf dem dynamischen Speicher, dem Heap, abgelegt werden! Insofern müsste der Speicher auch außerhalb der Funktion zugreifbar sein. 😕

    Oli



  • Aber die (Zeiger-) Variable ist im Stack!!!

    Damit wird der Zeiger ungueltig UND im Heap bleibt ein LOCH!



  • hi,

    unsigned char* ZDat1 = new unsigned char[8];
    for(int s = 0; s < 8; s++)
    {
    ZDat1[s] = s;
    }
    delete ZDat1;
    

    warum bleibt bei ZDat1 immer der Wert "" also kein Inhalt. Normal müsste doch nach dem schleifendurchlauf ZDat1[0] = 0, ZDat1[1] = 1 usw haben oder sehe ich da was falsch.

    ich versuche stück für stück einzugrenzen und alles nicht benötigte mal wegzulassen. bitte altenburger schlage nicht die hände über dem kopf ich habe mir alles selbst beigebracht ich hab niemals nur eine edv stunde erhalten ich kann nur aus fehlern lernen und was ich in meinen büchern finde.

    doch im augenblick ist schucht im schacht und morgen geht der 3 tag an dem ich an ein paar zeilen rumhacke und nicht einen millimeter vorwärts komme das ist frustrierend. 😉

    danke



  • DerAltenburger schrieb:

    Aber die (Zeiger-) Variable ist im Stack!!!

    Damit wird der Zeiger ungueltig UND im Heap bleibt ein LOCH!

    Und damit ist dein Problem gefunden! (Danke Altenburger für die lehrreiche Lektion.)

    waldsee schrieb:

    for(int s = 0; s < 8; s++)
    {
    ZDat1[s] = s;
    
    }
    

    Leider weist du hier nicht Zahlen sondern ASCII-Codes zu und 0 bis 7 sind keine druckbaren Zeichen.

    Probier's mal mit
    [cpp]for(int s = 0; s < 8; s++)
    {
    ZDat1[s] = s + 48;
    }
    [/cpp]
    dann siehst du auch die Zahlen.

    Zur Lösung deines Problem musst du dein char-Feld also außerhalb der Funktion und zwar in der rufenden Funktion anlegen. D.h. du musst für deine Struct Speicher reservieren, den du dann auch mit Hilfe andere Funktionen füllen kannst. Alles klar? 😃

    Du schaffst das!

    Oli



  • ob ich das schaffe weis ich nicht. ich werde es auf jeden fall selbst versuchen wollen. ich werde auf alle fälle bescheid geben ob es klappt oder nicht.

    aus fehlern wird man schlau. dann hab ich noch ne menge fehler vor mir 😃

    danke oli und altenburger



  • Bitte auch beachten:

    Wenn Speicher mit

    new[...]
    

    geholt wird, muss er auch mit

    delete[]
    

    gelöscht werden.

    Gruß Nighthero



  • Nochmal hierzu:

    DerAltenburger schrieb:

    Aber die (Zeiger-) Variable ist im Stack!!!

    Damit wird der Zeiger ungueltig UND im Heap bleibt ein LOCH!

    Habe folgenden Code erfolgreich getestet (Ausgaben als Kommentar):

    void dosth(char*& pt)
    {
    	char msg[64];
    	char* ch = new char[10];
    	for(int i=0; i<10; ++i)
    		ch[i] = i+48;
    	Memo1->Lines->Add(ch);  // 0123456789
    	sprintf(msg,"Adresse: %p", ch); // Adresse: 008E3F9C
    	Memo1->Lines->Add(msg);
    	pt = ch;  // Adresse des dynamisch erstellten Speicherbereichs
    	          // an übergebenen Parameter zuweisen
    	sprintf(msg,"Adresse: %p", pt); // Adresse: 008E3F9C
    	Memo1->Lines->Add(msg);
    }
    
    void func()
    {
    	char msg[64];
    	char* ptr = 0;
    	dosth(ptr);
    	Memo1->Lines->Add(ptr);  // 0123456789
    	sprintf(msg,"Adresse: %p", ptr); // Adresse: 008E3F9C !!!
    	Memo1->Lines->Add(msg);
    	delete[] ptr; // !!!!!!!!!!!!!!!!!!!
    }
    

    D.h. bei Übergabe einer Referenz des char ptr* nimmt er die Adresse auch an. Definiere ich den Funktionskopf allerdings so:

    void dosth(char* pt);
    

    funktioniert es nicht. Ist der Grund die Übergabe einer Kopie?

    Jedenfalls, waldsee, kannst du entsprechend einfach eine Referenz (keinen Zeiger) auf deine Struct übergeben und müsstest entsprechend die dynamisch erzeugten Werte zuweisen können. Das wäre ein minimaler Änderungsaufwand 🤡

    Oli



  • im augenblick versteh ich nur bahnhof, es muss irgendwo in der übergabe bei mir scheitern. ich muss aber jetzt erst mal ein wenig meinen kopf sammeln das war zuviel die letzten tage für meine rübe oder sollte ich es mal mit alohol versuchen wenn ich die leute heut gesehen habe bin ich mir sicher das ein grosser teil die heut unterwegs waren keine probleme mit einem zeiger haben 😃
    Das einzigste Zeigerproblem wird der Zeiger im Wecker sein der morgen früh bimmelt 🙂

    waldsee



  • char* ch = new char[10];
    

    was ich jetzt aber nicht ganz verstehe ist warum du in der funktion dosth nicht delete ch; brauchst?



  • weil du ja sonst den dynamisch zugewiesenen speicher, der auf dem heap angelegt wird und auf den ich mit dem Zeiger ptr in func() zugreifen will, wieder freigeben würdest!!! dann würdest du wiederum mit ptr ins Leere greifen.

    So richtig sauber ist diese Lösung allerdings nicht, da man leicht den Überblick über angelegten und freigegebenen Speicher verlieren kann...

    gruß oli



  • kann ich eine array das ich mit new erzeugt hab in einer anderen funtion zerstören z.B. nachdem es gespeichert wurde oder muss dies immer in einer funktion geschehen?



  • ja, du kannst den speicher auch in einer anderen funktion freigeben, wie ich es im beispiel angegeben habe.

    der speicher im heap existiert ja solange, bis du delete bzw. delete[] aufrufst oder das programm beendet wird. wenn du also einen zeiger auf den speicherbereich im heap hast, kanns du den dynamischen speicher dort abräumen.

    oli



  • wenn ich aus einer anderen funktion versuche aufzuheben

    delete[] ZDat1;
    

    erhalte ich immer undefiniertes Symbol als Fehlermeldung da es auserhalb des Bereiches liegt.

    waldsee



  • Wenn ich dich richtig verstanden habe, machst du folgendes:

    void funcA()
    {
       // ...
       char* ZDat1 = new char[10];
       // ...
    }
    
    void funcB()
    {
       // ...
       delete[] ZDat1;
       // ...
    }
    

    Das kann natürlich nicht gehen, weil ZDat1 in funcB ja nicht definiert ist. Klar. Du brauchst in funcB einen gültigen Zeiger auf den von ZDat1 reservierten Speicher, den du wie folgt bekommst:

    void funcA(char*& ptr_aus_B)
    {
       // ...
       char* ZDat1 = new char[10];
       ptr_aus_B = ZDat1; // weist dem übergebenen Pointer die Adresse von ZDat1 zu
       // ...
    }
    
    void funcB()
    {
       // ...
       char* ptr;
       funcA(ptr)
       delete[] ptr; // gibt den Speicher frei, den ZDat1 reserviert hat
       // ...
    }
    

    Schlaf mal ein bisschen, dann geht's wieder 😃

    Lieben Gruß, Oli



  • hallo
    danke dir jetzt hab ich die logik versanden. klar das eine ist nur ein zeiger auf den anderen und wird somit freigegeben.

    du glaubst nicht wie ich auf kohlen sitze habe jetzt monate in ein project gesteckt und jetzt knallt es auf einmal und zieht sich durch das ganze projekt.

    jetzt gehts wirklich in die kiste um den kopf zu säubern

    danke nochmal an alle helfer

    waldsee 👍



  • der oli schrieb:

    Nochmal hierzu:

    DerAltenburger schrieb:

    Aber die (Zeiger-) Variable ist im Stack!!!

    Damit wird der Zeiger ungueltig UND im Heap bleibt ein LOCH!

    Habe folgenden Code erfolgreich getestet (Ausgaben als Kommentar):

    void dosth(char*& pt)
    {
    .
    .
    }
    

    D.h. bei Übergabe einer Referenz des char ptr* nimmt er die Adresse auch an. Definiere ich den Funktionskopf allerdings so:

    void dosth(char* pt);
    

    funktioniert es nicht. Ist der Grund die Übergabe einer Kopie?

    Ohne Referenz musst Du einen Zeiger auf einen Zeiger uebergeben!!! Nur dann Kannst Du den Inhalt des Zeigers - die Adresse!!!- aendern und den Inhalt, wohin der Zeiger zeigt!
    Beide Faelle muessen dann unterschiedlich dereferenziert werden!!!

    PS: Besorg Dir mal ein Buch / Tut zu Zeigern und Zeiger auf Zeiger!!!



  • Jetzt ist's mir um einiges klarer. Danke.

    oli


Anmelden zum Antworten