![]() |
pchar freigeben?
muss man einen pchar eigentlich freigeben? und wenn ja, wie?
ich hab hier ein programm, bei dem der Programmierer jeden lokalen pchar am Ende der procedure auf nil gesetzt hat:
Delphi-Quellcode:
temp: PChar;
begin ... temp:= nil end; |
Re: pchar freigeben?
das setzen des Zeigers auf nil gibt keinen Speicher frei, damit kriegst du ein schönes Speicherleck. Das Gegenmittel heißt
![]() greetz Mike |
Re: pchar freigeben?
Zitat:
ist FreeMem bei lokalen PCHars eigentlich nötig, oder macht delphi das nach ende der procedure selbst? |
Re: pchar freigeben?
Da PChar nur eine Zeigertyp ist (Zeiger auf einen Char) ist ein Freemem eigentlich nicht nötig. Man muß u.U. aber den Speicher der Struktur freigeben auf welchen der pchar gesetzt wurde.
|
Re: pchar freigeben?
Zitat:
vielen dank |
Re: pchar freigeben?
GetMem/FreeMem oder besser New/Dispose wird nur benötigt, wenn du z.B. PChars an Funktionen übergibst und diese den "Inhalt" des PChars verändern. :)
|
Re: pchar freigeben?
Zitat:
|
Re: pchar freigeben?
Weil dann ein neues Pchar erzeugt wird.
|
Re: pchar freigeben?
Ich fürchte hier herrscht Verwirrung über die Bedeutung von "PChar" und "C-String".
Eine Variable vom Typ PChar, vollkommen egal ob lokal oder global, muss nicht freigegeben werden. Ist die lokal, wird sie auf dem Stack abgelegt und beim Unrolling auch wieder davon entfernt, genauso wie alle lokalen Variablen. Globale Variablen haben ihren Speicherplatz im Image des Codes, sie existieren ohnehin über die gesamte Programmlaufzeit hinweg. In der Tat ist es gar nicht möglich, eine Variable wieder freizugeben. Habe ich eine Schleifenvariable i vom Typ Integer, die ich nach der Ausführung der Schleife nicht wieder benötige, ist es (praktisch) unmöglich, diese Variable i wieder aus dem Stack zu entfernen und den von ihr belegten Speicher wieder für andere Variablen zu benutzen. Bei einer Variable vom Typ PChar ist das nicht anders, ich kann den Speicherplatz (heute noch 4 Byte) nicht wieder freigeben. Die 4 Byte hinter dem PChar können allerdings als Pointer interpretiert werden, der auf einen bestimmten Speicherbereich zeigt. Das wird in der Regel ein Block auf dem Heap sein. Diesen Block muss ich explizit reservieren (GetMem(), New(), HeapAlloc(), GlobalAlloc(), Konstruktor einer Klasse) und muss ihn daher genauso explizit wieder freigeben (FreeMem(), Dispose(), HeapFree(), GlobalFree(), Destruktor einer Klasse). Wenn ich also zunächst Speicher für meine PChar-Variable reserviere und anschließend einen String reinschreibe, muss ich den Speicher anschließend auch wieder freigeben, genauso wie ich ein Objekt durch einen Aufruf seines Destruktors zerstören muss (zumindest in Delphi). Die Variable lediglich auf den Wert nil zu setzen ist sinnlos. Wenn ich den Speicher noch nicht freigegeben habe, verliere ich damit die Referenz auf den Speicher (der somit allokiert bleibt). Wenn ich den Speicher bereits freigegeben habe, benötige ich eine Zuweisung auf nil nicht mehr. Da man PChars in der Regel auch zum Referenzieren von Speicherblöcken benutzt und nicht, weil sie bei den Variablen-Definitionen schick aussehen, muss man diese Speicherblöcke auch wieder freigeben. Die Aussage von mkinzler: Zitat:
Ein FreeMem() ist auf die Variable vom Typ PChar nicht anwendbar, es ist also nicht nicht nötig, sondern es ist gar nicht erst möglich. Ein FreeMem() auf den Speicherbereich, den die Variable vom Typ PChar referenziert (FreeMem(blubb), wenn blubb vom Typ PChar ist), ist auf jeden Fall nötig, sofern diese Variable einen Speicherbereich allokiert, der zuvor angefordert wurde (also dann, wenn man tatsächlich etwas mit seiner Variable macht). Besonders interessant wird es dann, wenn man eine Variable vom Typ PChar hat, die auf das erste Zeichen eines Pascal-Strings zeigt:
Delphi-Quellcode:
Hier vermischt man Compiler-Magic (Pascal-Strings) mit gewöhnlichem handmade Code. Es wird (dynamisch auf dem Heap) Speicher für den Pascal-String "Hello, world" reserviert. Gleichzeitig zeigt aber c auf das erste Zeichen. Beim verlassen der Funktion wird nun automagisch der Speicher des Strings freigegeben und somit auch der Speicherbereich, auf den c zeigt. Ein zusätzlichen Freigeben von c wäre hier unangebracht und würde zu einem Fehler führen, wenn der Compiler den Speicher für den String ein zweites Mal freigeben möchte (EInvalidPointer dürfte die Exception sein).
procedure DoSomething;
var s: String; c: PChar; begin s := 'Hello, world'; c := @s[1]; end; HTH |
Re: pchar freigeben?
vielen vielen dank für die ausführliche antwort !!!! :thumb:
aber eine frage hätte ich noch:
Delphi-Quellcode:
macht sowas sinn? wenn ich doch den p_char auf nil setz, dann kann ich doch den speichernbereich mit FreeMem nicht mehr freigeben, weil ich ja net weiß, wohin der p_char zeigt, oder?
p_char: PChar;
begin ... p_char := nil; FreeMem(p_char); end; // edit: ahh hier steht ja die antwort, sorry :-) Zitat:
|
Re: pchar freigeben?
Zitat:
folgendes in der reihenfolge kann eigentlich nie sinn machen, oder? p_char := nil; FreeMem(p_char); weil ich schnall irgendwie net, warum mein vorgänger, dass bei jedem p_char gemacht hat?! Ich würd auf sowas eigentlich schon gar nicht kommen?! |
Re: pchar freigeben?
Dein Code wird eine AV auslösen, weil, wie Thomas erklärt hat, mit nil die Referenz gelöscht wird, aber das wird sie sowieso nach verlassen der lokalen Routine. Allein das FreeMem ist wichtig, wenn du Speicher mit GetMem reervierst, um den Speicher wieder frezugeben und aufzuräumen.
|
Re: pchar freigeben?
hi luckie,
nee eben nicht, da werden keine av's ausgelöst. das ist ja eben das komische?! und der verwendet des wirklich überall im code??? |
Re: pchar freigeben?
Ja, weil FreeMem() intelligent ist und einen NULL/NIL Parameter handeln kann - sprich: ihn ignoriert. Das geht gehört mit dem Funktionssyntax AllocMem() ReAllocMem(), wobei letztere auch Speicher freigeben und den Zeiger bei einer Grösse von 0 auf Nil setzen. Trotzdem kann bei Verwendung eines solchen Codes immer FreeMem() am Ende aufgerufen werden, damit bei eventuell nicht auf eine Grösse von 0 reduzierte Bereiche freigegeben werden.
|
Re: pchar freigeben?
Zitat:
wenn ich aber jetzt alles von
Delphi-Quellcode:
in
p_char: PChar;
begin ... p_char := nil; FreeMem(p_char); end;
Delphi-Quellcode:
ändere, dann sollte es eigentlich keine probleme geben, oder?
p_char: PChar;
begin ... FreeMem(p_char); end; |
Re: pchar freigeben?
Zitat:
Zitat:
|
Re: pchar freigeben?
Zitat:
Kurzum, um folgende Frage zu beantworten: Zitat:
Zu deiner nil-Geschichte: Vielleicht ist dir in einigen Quellcodes schon aufgefallen, daß Objekte nicht mit objekt.Free() freigegeben werden, sondern mit FreeAndNil(objekt). Free() setzt, ebenso wie FreeMem() den Pointer *nicht* auf nil, sondern lässt ihn auf dem alten Wert (irgendwo im Speicher) und gibt lediglich den freigegebenen Speicher frei. Da mit FreeAndNil() meine Objektreferenz nil wird, kann ich zu einem späteren Zeitpunkt feststellen, ob mein Objekt freigegeben ist bzw ob ich mit meiner Objektreferenz tatsächlich noch ein existierendes Objekt habe. Genauso kann man es mit PChars machen. Erst freigeben und nachher selber af nil setzen (und nur in dieser Reihenfolge!). Dann kannst du später mit einer if-Abfrage überprüfen ob der PChar noch gültig ist. Wenn du das in deinem gesamten Programm konsequent durchziehst, kann man pauschal die Aussage treffen: Alle PChars, die nicht nil sind, verweisen auf einen gültigen Speicherbereich. Solche Aussagen können sich irgendwann mal als praktisch erweisen. Zitat:
Es ist in dieser Reihenfolge jedenfalls falsch und unsinnig. |
Re: pchar freigeben?
Zitat:
Vielen vielen Dank Tommie-lie genau auf so eine klipp und klare antwort habe ich gehofft :-) :thumb: :thumb: :thumb: |
Re: pchar freigeben?
Zitat:
Zitat:
Man muss halt genau sein, sonst heisst es ein halbes Jahr später wieder: "Aber du hattest doch geschrieben ..." und man stellt mit Entsetzen fest, es war nicht eindeutig formuliert bzw. derjenige denkt nicht an das an was ich damals dachte... |
Re: pchar freigeben?
Wenn du den Speicher selbst mit GetMem holst, und wenn du es `ganz´ sauber machen willst, dann schreibe es so:
Delphi-Quellcode:
var
p_char: PChar; begin ... GetMem(p_char, n_char); try ... finally FreeMem(p_char); end; end; |
Re: pchar freigeben?
Zitat:
Zitat:
Zitat:
![]() |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:51 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz