Results 1 to 10 of 10

Thread: CreateThread memory leak

  1. #1
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    289

    CreateThread memory leak

    Hoi

    Ik heb een thread probleempje waar een memory leak in op treed.
    Zodra de ProcessesToWatch array regel aanwezig is krijg ik een memory leak.
    Ik heb al van alles geprobeerd om deze op te lossen maar snap niet zo goed waarom hij op treed.

    Ik heb alles eruit gestript om het minimale over te houden en het te reproduceren.

    Wat mis ik hier nu?

    Code:
    program CreateThreadTest;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      WinAPI.Windows,
      System.SysUtils,
      Winapi.TlHelp32;
    
    type
      TProcMonParamsRec          = record
        WatchList        : TArray<string>;
      end;
      PProcMonParamsRec          = ^TProcMonParamsRec;
    
    var
      gProcMonParamsRec         : TProcMonParamsRec;
      gProcMonHandle           : THandle;
      gProcMonThreadID         : Cardinal;
      gProcMonFinished         : boolean;
    
      gTemp                    : TArray<string>;
    const
      gProcessesToWatch        : TArray<string> = ['notepad.exe', 'cmd.exe'];
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    function DoStartProcMon(P: Pointer): Dword; STDCALL;
    var
      ProcessesToWatch : TArray<String>;
    begin
      ProcessesToWatch := PProcMonParamsRec(P)^.WatchList;   // <-- MEMORY LEAK
    
      repeat
        Write ('.');
        Sleep (1000);
      until gProcMonFinished; // Keep thread running
    
      result := 0;
      SetLength (ProcessesToWatch, 0);   // <-- werkt niet
    end;
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    function StartProcMon(aWatchList : TArray<string>) : THandle;
    Begin
      gProcMonParamsRec.WatchList := aWatchList;
    
      result := CreateThread(NIL, 0, @DoStartProcMon, @gProcMonParamsRec, 0, gProcMonThreadID);
    End;
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    begin
      ReportMemoryLeaksOnShutDown := true;
    
      // *** MEMORY LEAK ***
      //Unexpected Memory Leak
      //An unexpected memory leak has occurred. The unexpected small block leaks are:
      //
      //13 - 20 bytes: Unknown x 1
      //21 - 28 bytes: UnicodeString x 1
      //29 - 36 bytes: UnicodeString x 2
    
      gProcMonFinished := false;
      gProcMonHandle := 0;
      try
        try
          gProcMonHandle := StartProcMon (gProcessesToWatch);
    
          readln;
    
        except
          on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
        end;
    
      finally
        CloseHandle(gProcMonHandle);
      end;
    
    
      // *** NO MEMORY LEAK ***
      // gTemp := gProcessesToWatch;
    
    end.

  2. #2
    Van Threads en Pointers heb ik weinig verstand, maar als je een pointer maakt voor een list, zal die list toch met minstens één element moeten zijn gevuld.
    Of maak ik hier een vergissing?

  3. #3
    Delphi kopieert arrays als referentie. Dat is wel snel, maar kan ook weleens voor ongewenst gedrag zorgen.
    Ik zie eerlijk gezegd niet precies wat hier mis gaat, maar je zou een kopie van die array kunnen maken m.b.v. Copy en kijken of dat het oplost:

    Delphi Code:
    1. // i.p.v. ProcessesToWatch := PProcMonParamsRec(P)^.WatchList;
    2.   ProcessesToWatch := Copy(PProcMonParamsRec(P)^.WatchList, 0, Length(PProcMonParamsRec(P)^.WatchList));
    1+1=b

  4. #4
    Ik heb ook een paar keer meegemaakt dat het probleem aan het gebruik van strings lag.
    Je zou eens kunnen proberen om string te veranderen naar Widestring.

    Code:
    type
      TProcMonParamsRec          = record
        WatchList        : TArray<Widestring>;
      end;
    Ik weet niet of het overal nodig is.

  5. #5
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    289
    Quote Originally Posted by GolezTrol View Post
    Delphi kopieert arrays als referentie. Dat is wel snel, maar kan ook weleens voor ongewenst gedrag zorgen.
    Ik zie eerlijk gezegd niet precies wat hier mis gaat, maar je zou een kopie van die array kunnen maken m.b.v. Copy en kijken of dat het oplost:

    Delphi Code:
    1. // i.p.v. ProcessesToWatch := PProcMonParamsRec(P)^.WatchList;
    2.   ProcessesToWatch := Copy(PProcMonParamsRec(P)^.WatchList, 0, Length(PProcMonParamsRec(P)^.WatchList));
    Helaas, dat maakte niets uit

  6. #6
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    289
    Quote Originally Posted by DragonFly View Post
    Ik heb ook een paar keer meegemaakt dat het probleem aan het gebruik van strings lag.
    Je zou eens kunnen proberen om string te veranderen naar Widestring.

    Code:
    type
      TProcMonParamsRec          = record
        WatchList        : TArray<Widestring>;
      end;
    Ik weet niet of het overal nodig is.
    Moest ze overal even aanpassen, dat gaat het al iets beter, nog maar 1 leak ipv 3.


    Unexpected Memory Leak
    An unexpected memory leak has occurred. The unexpected small block leaks are:

    13 - 20 bytes: Unknown x 1

  7. #7
    Je kan wel gewoon die Widestring terugzetten naar string indien gewenst en dan dit stukje aanpassen.

    Code:
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    var
      ProcessesToWatch : TArray<string>;
    function DoStartProcMon(P: Pointer): Dword; STDCALL;
    begin
      ProcessesToWatch := PProcMonParamsRec(P)^.WatchList;   // <-- MEMORY LEAK
    
      repeat
        Write ('.');
        Sleep (1000);
      until gProcMonFinished; // Keep thread running
    
      Result := 0;
      SetLength (ProcessesToWatch, 0);   // <-- werkt niet
    end;
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    ProcessesToWatch is nu globaal gemaakt. Dan gaat alles goed.
    Denk met die DLL StdCall het anders moet. Weet het verder ook niet.
    Succes.

  8. #8
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    289
    Quote Originally Posted by DragonFly View Post
    Je kan wel gewoon die Widestring terugzetten naar string indien gewenst en dan dit stukje aanpassen.

    Code:
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    var
      ProcessesToWatch : TArray<string>;
    function DoStartProcMon(P: Pointer): Dword; STDCALL;
    begin
      ProcessesToWatch := PProcMonParamsRec(P)^.WatchList;   // <-- MEMORY LEAK
    
      repeat
        Write ('.');
        Sleep (1000);
      until gProcMonFinished; // Keep thread running
    
      Result := 0;
      SetLength (ProcessesToWatch, 0);   // <-- werkt niet
    end;
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    ProcessesToWatch is nu globaal gemaakt. Dan gaat alles goed.
    Denk met die DLL StdCall het anders moet. Weet het verder ook niet.
    Succes.
    stom stom stom

    Ik had bovenstaande code uit een library unit gehaald maar gebruik het nu in een gewoon programma.
    Jouw opmerking "Denk met die DLL StdCall het anders moet" duwde me de juiste richting op, het is geen DLL.

    Het weghalen van STDCALL was voldoende ;-)

    Bedankt....

    Code:
    program CreateThreadTest;
    
    {$APPTYPE CONSOLE}
    
    {$R *.res}
    
    uses
      WinAPI.Windows,
      System.SysUtils,
      Winapi.TlHelp32;
    
    type
      TProcMonParamsRec     = record
        WatchList           : TArray<string>;
      end;
      PProcMonParamsRec     = ^TProcMonParamsRec;
    
    var
      gProcMonParamsRec     : TProcMonParamsRec;
      gProcMonHandle        : THandle;
      gProcMonThreadID      : Cardinal;
      gProcMonFinished      : boolean;
    
    const
      gProcessesToWatch     : TArray<string> = ['notepad.exe', 'cmd.exe'];
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\\
    function DoStartProcMon(P: Pointer): Dword;// STDCALL;  <-- FuckUp
    var
      ProcessesToWatch : TArray<string>;
    begin
      ProcessesToWatch := PProcMonParamsRec(P)^.WatchList;
    
      repeat
        Write ('.');
        Sleep (1000);
      until gProcMonFinished; // Keep thread running
    
      result := 0;
      SetLength (ProcessesToWatch, 0);
    end;
    
    function StartProcMon(aWatchList : TArray<string>) : THandle;
    Begin
      gProcMonParamsRec.WatchList := aWatchList;
    
      result := CreateThread(NIL, 0, @DoStartProcMon, @gProcMonParamsRec, 0, gProcMonThreadID);
    End;
    
    
    begin
      ReportMemoryLeaksOnShutDown := true;
      gProcMonFinished := false;
      gProcMonHandle := 0;
      try
        try
          gProcMonHandle := StartProcMon (gProcessesToWatch);
    
          readln;
    
        except
          on E: Exception do
            Writeln(E.ClassName, ': ', E.Message);
        end;
    
      finally
        CloseHandle(gProcMonHandle);
      end;
    
    end.

  9. #9
    Ja, nu zie ik het ook

  10. #10
    Win32.Trojan.Heur.Herby
    Join Date
    Dec 2003
    Location
    Nuenen of all places
    Posts
    289
    Quote Originally Posted by DragonFly View Post
    Ja, nu zie ik het ook
    Toch bedankt.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •