![]() |
ReportMemoryLeaksOnShutDown
Ist true
Und die Meldung siehe Anhang. Nur was soll ich damit anfangen? Jemand eine Idee wie man die besser Analysieren kann? EurekaLog taugt auch nichts. Ich exportiere einen String (PAnsiChar) aus einer DLL Die Rückgabe kann ich ja schlecht löschen.
Delphi-Quellcode:
ExportPtr wird mit
ExportPtr := AnsiStrAlloc(Length(strExport) + 1);
CopyMemory(ExportPtr, PAnsiChar(AnsiString(strExport)), Length(strExport) + 1); Result := ExportPtr;
Delphi-Quellcode:
StrDispose(ExportPtr);
freigegeben wenn die Anwendung(DLL) beendet wird. EurekaLog zeigt immer nur auf die Funktion die ExportPtr zurück gibt aber nicht wo und warum der Leak entsteht. Den String kann ich nicht freigeben solange er in der Anwendung selbst verwendet wird. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
|
AW: ReportMemoryLeaksOnShutDown
Zitat:
Zitat:
Delphi-Quellcode:
Result := GetExportPtr(Path, Delimiter); // PWideChar
EurekaLog springt immer in diese Zeile nur was nutzt mir das der String wird ja in dieser einen Zeile nicht verarbeitet (zugewiesen) StrDispose(Result) oder StrDispose(ExportPtr) direkt nach Result würde ja die Rückgabe aus der DLL löschen. Die erste Zeile ist x.dll SysUtils AnsiStrAlloc und dann kommt x.dll MyExport GetExportPtr Damit finde ich aber den Leak nicht. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
|
AW: ReportMemoryLeaksOnShutDown
Zitat:
PWideChar war falsch. strExport ist ein String der nach Ordnern sucht diese werden dann addiert in diesen Format.
Delphi-Quellcode:
ergibt dann
strExport := strExport + FolderFound + Delemiter;
'Folder1, Folder2, Folder3' usw. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Delphi-Quellcode:
Also liefert die Funktion ein PAnsiChar, welches dann mittels String-Verknüpufung weiterverwendet wird?
var
strExport: string; FolderFound: string; begin // [...] strExport := 'Folder1'+ Delimiter; FolderFound := DeineFunktionDieDieDllAufruft; strExport := strExport + FolderFound + Delimiter; // [...] end; Dann würde ich die Funktion so umschreiben, dass sie einen String zurückliefert. Nach Zuweisung des PAnsiChars auf Result kannst Du den PAnsiChar freigeben. |
AW: ReportMemoryLeaksOnShutDown
Delphi-Quellcode:
function ExpFindFolders(Path: PAnsiChar; Delimiter:AnsiChar=','): PAnsiChar; stdcall;
begin Result := GetExportPtr(Path, Delimiter); // Hier bleibt EurekaLog stehen damit kann ich aber nichts anfangen. end;
Delphi-Quellcode:
Was verursacht den Leak "AnsiStrAlloc" ?
function GetExportPtr(Path, Delimiter): PAnsiChar;
var strExport: string; begin // [...] ExportPtr := AnsiStrAlloc(Length(strExport) + 1); CopyMemory(ExportPtr, PAnsiChar(AnsiString(strExport)), Length(strExport) + 1); Result := ExportPtr; end; Ich kann keinen string zurückgeben die DLL kann auch mit anderen Developer Sprachen verwendet werden. Strings zwischen DLL und Anwendung hin und her schieben ist nicht das wahre. Es muss ein 'PAnsiChar' oder PWideChar sein. |
AW: ReportMemoryLeaksOnShutDown
Ist die EXE und die DLL von Dir ? Dann schreib Dir die Freigabe-Routinen. Oder übergib halt einen schon erstellten und genullten Speicher, wenn Du sicher sagen kannst, wieviel Speicher ausreicht und er wird einfach nur gefüllt.
Generell als Faustregel gilt, dass Speicher dort freigegeben werden sollte, wo er erstellt wird. Also sagen wir, die DLL erstellt den Speicher, dann gibt die DLL den auch frei. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Delphi-Quellcode:
StrDispose(ExportPtr);
Wenn die DLL beendet wird. Sehe schon muss mich da selbst durchbeißen wie auch immer. Danke. Frage mich nur was das ReportMemoryLeaksOnShutDown bringen soll wenn solche Informationen alles ist was dabei herumkommt. Ein leerer Dialog würde es dann auch tun oder keine Meldung. |
AW: ReportMemoryLeaksOnShutDown
Vielleicht solltest Du mal allen relevanten Code zeigen. Was ich hier sehe ist nur ein Schnipsel aus der DLL (vermute ich) und ein StrDispose, wo nirgends gesagt wird, wann und unter welchen Umständen etwas freigegeben wird.
Die Fehlermeldung zeigt mehrere Speicherlecks, nicht nur eins. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Kann den Original Quelltext leider nicht zeigen. Trotz allem nochmals Danke für den Versuch zu helfen. |
AW: ReportMemoryLeaksOnShutDown
OK, also hatte ich recht und das Leak kann einfach geschlossen werden, indem man die Funktion eien String zurückliefern lässt und den PAnsiChar noch in der Funktion frei gbit.
|
AW: ReportMemoryLeaksOnShutDown
Zitat:
Selbst wenn du recht hast was ich dir nicht absprechen will. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Delphi-Quellcode:
Probier's aus, das Leak wird weg sein.
function GetExportPtr(Path, Delimiter): string;
var strExport: string; begin // [...] ExportPtr := AnsiStrAlloc(Length(strExport) + 1); CopyMemory(ExportPtr, PAnsiChar(AnsiString(strExport)), Length(strExport) + 1); Result := ExportPtr; StrDispose(ExportPtr); end; |
AW: ReportMemoryLeaksOnShutDown
Delphi-Quellcode:
ExportPtr ist PAnsiChar und kann so nicht als String zurück gegeben werden.
Result := ExportPtr;
gruss |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Der Compiler erzeugt den notwendigen Code. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Und ich sehe nur Kauderwelsch nicht wirklich noch irgendetwas mit einem identifizierbaren string zu tun.
Delphi-Quellcode:
Result := string(AnsiString(ExportPtr));
|
AW: ReportMemoryLeaksOnShutDown
Stopp, ich muss mich entschuldigen, ich habe Blödsinn geschrieben, weil ich was falsch verstanden hatte.
Du hast eine DLL, die Du in Delphi schreibst und die diese Funktion exportiert:
Delphi-Quellcode:
Korrekt?
function GetExportPtr(Path, Delimiter): PAnsiChar;
var strExport: string; begin // [...] ExportPtr := AnsiStrAlloc(Length(strExport) + 1); CopyMemory(ExportPtr, PAnsiChar(AnsiString(strExport)), Length(strExport) + 1); Result := ExportPtr; end; Und diese Funktion soll nicht nur von Delphi aus sondern auch aus anderen Programmiersprachen heraus aufgerufen werden können. (Irgendwas stimmt da nicht, die Parameter haben keinen Typ.) Prinzipiell ist es bei der Übergabe von Strings an DLLs so, dass man sich entscheiden muss, wer den Speicher alloziert und wer ihn frei gibt. Üblicherweise macht das der Aufrufer:
Delphi-Quellcode:
In der DLL wird dann der übergebene Speicherbereich gefüllt:
var
Res: integer; Buffer: Array[0..255] of AnsiChar; s: AnsiString; begin Res := MyDllFunction(@Buffer, SizeOf(Buffer)); s := PAnsiChar(@Buffer); end;
Delphi-Quellcode:
Die Alternative wäre, dass die DLL eine Funktion exportieren muss, die Speicher frei gibt. An die übergibt man dann den aus der DLL zurückgelieferten PAnsiChar zur Freigabe. Das ist aber in der Regel zu aufwändig.
function MyDllFunction(_Buffer: PAnsiChar): integer; stdcall;
var s: string; as: AnsiString; begin s := IrgendwasDasDenStringLiefert; as := s; StrCopy(PAnsiChar(as[1]), _Buffer); Result := Length(as); end; |
AW: ReportMemoryLeaksOnShutDown
Ich habe auch schon Windows-API Funktionen gesehen, die dann ihre Freigabe-Routine mitgeben. Man macht das im Aufruf dann so :
Code:
Wie Du siehst, Die DLL stellt dir 2 Funktionen zur Verfügung, da sie den Speicher alloziert und deswegen auch wieder freigeben muss.
const
CurrentServerHandle = 0; WTSEnumerateSessions : TWTSAPI32_WTSEnumerateSessions = NIL; WTSFreeMemory : TWTSAPI32_WTSFreeMemory = NIL; procedure ShowSessions; var Count : DWord; pSessionInfo : pTWtsSessionInfo; begin Lib := LoadLibrary('WTSAPI32.DLL'); @WTSEnumerateSessions := GetProcaddress(Lib, pChar('WTSEnumerateSessionsW')); @WTSFreeMemory := GetProcaddress(Lib, pChar('WTSFreeMemory')); if WTSEnumerateSessions(CurrentServerHandle, 0, 1, pSessionInfo, Count) then begin // DoSometing end; WTSFreeMemory(pSessionInfo); end; Ist es eine fixe Länge kannst Du auch den schon allozierten Speicher als Parameter übergeben und auf Deiner Seite dann auch wieder freigeben (was dummzeuch ja auch schon geschrieben hatte). Was du NICHT machen kannst ist Speicher in der DLL allozieren und beim Aufrufer in der Exe freigeben, weil das unterschiedliche MemoryManager sind. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
PS: Bei Übergabe einer "echten" Konstante (nicht typisiert) an PChar, kann man den Cast weglassen, und Delphi sich den richtigen Typ aussuchen lassen.
Delphi-Quellcode:
Wobei ich selbst keine LoadLibrary/GetProcAddress mehr verwende, sondern entweder statische Links oder die statischen über Delayed-Loading, wenn es sich um APIs handelt, die es nicht immer gibt, oder es DLLs sind, die nicht beim Start direkt geladen werden sollen.
GetProcaddress(Lib, 'WTSEnumerateSessionsW');
|
AW: ReportMemoryLeaksOnShutDown
Ihr könntet auch mal ruhig auf die Ursprungsfrage eingehen und mitteilen, dass das setzen von ReportMemory...usw. auf True zwar ganz nett ist, aber sich zum Richtigen FastMM4 wie ein Dreirad zu einem Traktor verhält.
Venice2, nehme dir doch bitte 10 Minuten Zeit und schaue dir an, wie man den FastMM4 extern einbindet und das entstehende Log lesen lernt: ![]() |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Danke für den Rat. |
AW: ReportMemoryLeaksOnShutDown
Habe mir das Video angesehen und eingerichtet.
Ändert aber nichts an der Ausgabe ausgenommen das Log ist etwas detaillierter und gibt mir genau das aus was ich schon wusste.
Delphi-Quellcode:
Result := GetExportPtr(Path, Delimiter); // Hier bleibt EurekaLog stehen damit kann ich aber nichts anfangen.
Das wird so auch in das Log geschrieben das in dieser Funktion etwas nicht freigegeben wird. Was das ist, ist mir ebenfalls bekannt. Ich alloziere Speicher der nicht freigegeben wird (angeblich). Ich bekomme hier 14 Speicher Lecks weil ExportPtr 14 mal aufgerufen wird innerhalb einer schleife und die größe des Speichers anhand des Strings strExport neu zugewiesen wird.
Delphi-Quellcode:
ExportPtr := AnsiStrAlloc(Length(strExport) + 1);
ExportPtr Seltsam ist nur das ich ihn freigebe wenn die DLL beendet wird und zwar in Destroy.
Delphi-Quellcode:
EDIT:
destructor TMyLib.Destroy;
begin StrDispose(ExportPtr); end; OK. Das ist mein Fehler. Zitat:
Aber! Wenn ich diesen jedesmal innerhalb der Schleife neu Alloziere dann Alloziere ich 14x mal neuen Speicher und der vorherige wird nicht freigegeben. Ich habe die Zuweisung jetzt aus der Schleife herausgenommen und weise den Speicher erst zu wenn strExport sein Maximum(Length) erreicht hat. Also einmalig direkt nach der Schleife! Siehe da die Speicherlecks sind weg. |
AW: ReportMemoryLeaksOnShutDown
Oft ist ja gar nicht kaputt, sondern man selbst das Problem! :stupid:
|
AW: ReportMemoryLeaksOnShutDown
Zitat:
Einer muss ja den absoluten Top Level haben wenn nicht ich dann du vielleicht. Aber was weis ich schon. |
AW: ReportMemoryLeaksOnShutDown
Na na, Humor ist, wenn man trotzdem lacht.
Das kennt doch jeder von uns. Man debuggt sich nen Wolf, macht und tut ewig und drei Tage und am Ende ändert man nur ein, zwei, drei Zeilen und schon geht’s. Hinterher ist man immer schlauer und wundert sich, warum man nicht gleich drauf gekommen ist. Aber ist halt so, dass ist halt menschlich. Wichtig ist, dass man dran bleibt und nicht aufgibt. |
AW: ReportMemoryLeaksOnShutDown
Zitat:
Ist manchmal zum Haare raufen. Alles gut. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:53 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