Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   MemLeak, aber wo??? (https://www.delphipraxis.net/160427-memleak-aber-wo.html)

snook 12. Mai 2011 11:46

MemLeak, aber wo???
 
FastMM4 zeigt mir in der proc UpdateInfoTable nen leak an, genaueres zur methode wird dann aber nciht mehr angezeigt

jedenfalls sind die ganzen zugirffe auf die IDataModule leckfrei. es kann eigentlich nur irgendwie mit den PChars zu tun haben. oder ich geb nen Item (PPlugInInfoTable) nicht richtig frei. hab jetzt aber schon solange draufgestarrt, dass ich nciht mehr durchblicke.

Delphi-Quellcode:

  PPlugInInfoTable = ^TPlugInInfoTable;
  TPlugInInfoTable = packed record
    Name, Dll,
    Date, Author: PChar;
    Status     : TPlugInStatus;
    GUID       : PChar;
    Handle     : Cardinal;
    Version    : real;
  end;

function CopyPChar(Source: PChar): PChar;
var dummy: ansistring;
begin
  result := nil;
{  if length(Source) > 0 then
    StrAlloc(result, StrLen(@Source[1]) + 1)
  else
    StrAlloc(result, 1);
  StrCopy(result, Source);}
  result := StrNew(Source);
end;

function StringToPchar(s: ansistring): PChar;
begin
  if length(s) > 0 then
    result := CopyPChar(@s[1])
  else
    result := CopyPChar(nil);
end;

procedure FreePChar(Ch: PChar);
begin
  StrDispose(Ch);
  Ch := nil;
end;

procedure NewInfoItem(out PItem);
begin
  new(PPlugInInfoTable(PItem));
  with(PPlugInInfoTable(PItem)^) do
  begin
    Name := nil;
    Dll  := nil;
    Date := nil;
    Author:= nil;
    GUID := nil;
    Status:= psNil;
    Handle:= 0;
  end;
end;

procedure DisposeInfoItem(PItem: PPlugInInfoTable);
begin
  if Assigned(PItem^.Name) then FreePChar(PItem^.Name);
  if Assigned(PItem^.Dll) then FreePChar(PItem^.Dll);
  if Assigned(PItem^.Date) then FreePChar(PItem^.Date);
  if Assigned(PItem^.Author) then FreePChar(PItem^.Author);
  if Assigned(PItem^.GUID) then FreePChar(PItem^.GUID);
  dispose(PItem);
  PItem := nil;
end;

procedure TPlugInMain.UpdateInfoTable;
var LAdapter: IAdapter;
    LExtAdapter: IPlugInDllAdapter;
    DataTable, PlugInTable, Entry,
    AdapterModule, AdapterEntry: IDataModule;
    PlugIn : IPlugIn;
    PItem,
    PDummy : PPlugInInfoTable;
    i,lCount: integer;
    s      : string;
begin
  while FInfoTableList.Count > 0 do
  begin
    PItem := FInfoTableList[0];
    disposeInfoItem(PItem);
    FInfoTableList.Delete(0);
  end;

  FData.GetDataTableLib(DataTable);
  if Assigned(DataTable) then
    try
      DataTable.GetFirstDataModule(Entry);
      while Assigned(Entry) do
        try
          NewInfoItem(PDummy);
          PDummy^.Name := copyPChar(Entry.GetCharValue(PChar('Name')));
          PDummy^.Dll := copyPChar(Entry.GetCharValue(PChar('DLLFile')));
          FData.GetPlugInLibrary(Entry.GetCharValue(PChar('DLLFile')),PlugInTable);
          if Assigned(PlugInTable) then
            try
              PDummy^.Date := StringToPChar(
                              DateToStr(PlugInTable.GetFloatValue(PChar('Date'))) + ' ' +
                              TimeToStr(PlugInTable.GetFloatValue(PChar('Date')))
                                           );
              GetDllAdapter(PlugInTable.GetIntValue(PChar('Handle')),LAdapter);
            finally
              PlugInTable := nil;
            end;
          if Assigned(LAdapter) then
            try
              if LAdapter.QueryInterface(IPlugInDllAdapter,LExtAdapter) = 0 then
                try
                  LExtAdapter.GetPlugInTable(AdapterModule);
                  if Assigned(AdapterModule) then
                    try
                      AdapterModule.GetDataModule(PDummy^.Name,AdapterEntry);
                    finally
                      AdapterModule := nil;
                    end;
                finally
                  LextAdapter := nil;
                end;
            finally
              LAdapter := nil;
            end;
          if Assigned(AdapterEntry) then
            try
              PDummy^.Author := CopyPChar(AdapterEntry.GetCharValue(PChar('Author')));
              PDummy^.GUID  := CopyPChar(AdapterEntry.GetCharValue(PChar('GUID')));
              PDummy^.Version:= AdapterEntry.GetFloatValue(PChar('Version'));
            finally
              AdapterEntry := nil;
            end;
          FData.GetPlugInLibraryTable(Entry.Name,lCount,PlugInTable);
          if Assigned(PlugInTable) then
            try
              for i := 0 to lCount - 1 do
              begin
                NewInfoItem(PItem);
                if lCount = 1 then
                  Pitem^.Name  := CopyPChar(PDummy^.Name)
                else
                begin
                  s := PDummy^.Name;
                  Pitem^.Name  := StringToPChar(s + '('+IntToStr(i)+')');
                end;
                Pitem^.Dll   := CopyPChar(PDummy^.Dll);
                PItem^.Author := CopyPChar(PDummy^.Author);
                PItem^.GUID  := CopyPChar(PDummy^.GUID);
                PItem^.Date  := copyPChar(PDummy^.Date);
                PItem^.Version:= PDummy^.Version;
                FData.GetPlugIn(StrToInt(Entry.Name),i,PlugIn);
                if Assigned(PlugIn) then
                  try
                    PItem^.Handle := PLugIn.MsgHandle;
                    PItem^.Status := TPlugInStatus(IntToOrd(
                      SendMessage(PlugIn.MsgHandle,PM_QUERYSTATUS,MsgHandle,0)));
                  finally
                    PlugIn := nil;
                  end;
                FInfoTableList.Add(PItem);
              end;
              if Assigned(PItem) then
              begin
                PItem := nil;
                DisposeInfoItem(PDummy);
              end
              else
                FInfoTableList.Add(PDummy);
            finally
              PlugInTable := nil;
            end;
        finally
          DataTable.GetNextDataModule(Entry);
        end;
    finally
      DataTable := nil;
    end;
end;

SirThornberry 12. Mai 2011 12:07

AW: MemLeak, aber wo???
 
Kann es sein das .GetCharValue Speicher anfordert für den PChar den du da zurück bekommst?

snook 12. Mai 2011 12:19

AW: MemLeak, aber wo???
 
eigentlich nicht oder?

Delphi-Quellcode:

function TCustomDataModule.GetCharValue(AKey: PChar): PChar;
var index: integer;
begin
  result := PChar('');
  index := IndexOf(AKey);
  with FList.LockList do
    try
      if (index > -1) and
         (PDataModuleItem(Items[index])^.datatype = STR_DATA) then
          result := PChar(PDataModuleItem(Items[index])^.Value);
    finally
      FList.UnlockList;
    end;
end;
mir fiel gerade noch ein, dass es evtl möglich ist, dass die PChars bei nem new(PItem) evtl vorinitialisiert werden mit irgend nem wert? so ala fillchar?

SirThornberry 12. Mai 2011 12:59

AW: MemLeak, aber wo???
 
die werden maximal mit 0 initialisiert. Aber speicher verbraucht das nicht (es wird ja nur der Pointer gesetzt aber kein Speicher angefordert)

Wenn du wirklich denkst es liegt an den PChars, dann zähle doch einfach mal wie oft du mit CopyPChar und StringToPchar speicher anforderst und ob du genau so oft den Speicher mit FreePChar frei gibst.

Oder wird dir die Funktion nur angezeigt weil der Speicher der beim letzten Aufruf angefordert wurde nirgends mehr frei gegeben wird beim beenden des Programms?
1. Durchlauf: keinen Speicher freigeben, neuen Speicher(x1) für PChars etc. anfordern
2. Durchlauf: Speicher(x1) freigeben, neuen Speicher(x2) für PChars etc. anfordern
Programmende: Speicher(x2) wurde noch nicht frei gegeben?

snook 14. Mai 2011 15:36

AW: MemLeak, aber wo???
 
soo dank dir für die hilfe, hab mich da jetzt durchgekämpft und das leak gefunden. es war in einer dll. beim aufruf der methode
Delphi-Quellcode:
LExtAdapter.GetPlugInTable
. da würde mich mal interssieren ob fastmm4 deswegen nicht die methode angezeigt hat. kann es sein daa man dlls nicht untesuchen kann? hab mich an das dll-tutorial im fastmm4 gehalten.

omata 14. Mai 2011 16:23

AW: MemLeak, aber wo???
 
Zitat:

Zitat von sebastian paeckel (Beitrag 1100778)
kann es sein das man dlls nicht untesuchen kann?

Hast du die DLL denn mit Debug-Informationen kompiliert?

snook 14. Mai 2011 17:43

AW: MemLeak, aber wo???
 
Liste der Anhänge anzeigen (Anzahl: 1)
einstellungen sind auf dem screenshot.
bin noch icht so ganz drin in fastmm :(

omata 14. Mai 2011 18:19

AW: MemLeak, aber wo???
 
Zitat:

Zitat von sebastian paeckel (Beitrag 1100788)
einstellungen sind auf dem screenshot.
bin noch icht so ganz drin in fastmm :(

Das hat mit FastMM nichts zu tun.

Die Einstellung ist unter "Linker" zu finden (TD32-Debug-Info), danach Projekt->Projekt erzeugen aufrufen.

snook 14. Mai 2011 20:52

AW: MemLeak, aber wo???
 
ja nee das meinte ich nciht. wollte damit zum ausdruck bringen, dass ich nicht genau weiß welche einstellungen nötig sind, damit fastmm z.b. auch dll's debugged, bzw. die maximal möglichen infos rausgezogen werden können


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:49 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 by Thomas Breitkreuz