Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Leak im THtmlViewer finden (https://www.delphipraxis.net/125719-leak-im-thtmlviewer-finden.html)

Assertor 10. Dez 2008 12:50


Leak im THtmlViewer finden
 
Hallo,

ich brauch mal etwas Hilfe: Ich muß ein Memory- und Resourcen-Leak im THtmlViewer finden.

Die Probleme liegen in der Druckfunktion:

1) Wenn der FastMM4 im FullDebugMode läuft, kann man nur wenige male mit THtmlViewer Drucken, bevor eine Exception kommt. Diese bezieht sich auf eine ungültige GetMem Operation. Log anbei.

2) Der Druck im THtmlViewer führt zu Handle Leaks. Bei jedem Druck wird mindestens 1 Resource-Handle zusätzlich belegt.

Testcode (in leerem Projekt):

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  hv: THTMLViewer;
begin
  Button1.Enabled := False;
  FastMM4.ScanMemoryPoolForCorruptions;
  hv := THTMLViewer.Create(nil);
  try
    hv.Parent := Self;
    hv.LoadFromFile('d:\downloads\test.html');
    hv.Print(1, 1);
  finally
    hv.Free;
    Button1.Enabled := True;
  end;
  FastMM4.ScanMemoryPoolForCorruptions;
end;
Wenn man den Button 2-3x mit FastMM drückt kommt:
Zitat:


--------------------------------2008/12/10 13:40:41--------------------------------
FastMM has detected an error during a free block scan operation. FastMM detected that a block has been modified after being freed.

Modified byte offsets (and lengths): 4(1)

The previous block size was: 36

This block was previously allocated by thread 0x15C8, and the stack trace (return addresses) at the time was:
403226 [System.pas][System][@GetMem][3412]
520717 [Htmlview.pas][Htmlview][THTMLViewer.Create][666]
527543 [Unit2.pas][Unit2][TForm1.Button1Click][39]
476A61 [Controls.pas][Controls][TControl.Click][6758]
47AA44 [Controls.pas][Controls][TWinControl.WndProc][9336]
451761 [StdCtrls.pas][StdCtrls][TButtonControl.WndProc][4269]
47AB94 [Controls.pas][Controls][DoControlMsg][9405]
47AA44 [Controls.pas][Controls][TWinControl.WndProc][9336]
48DFC1 [Forms.pas][Forms][TCustomForm.WndProc][3902]
47A15B [Controls.pas][Controls][TWinControl.MainWndProc][9065]
42D99E [Classes.pas][Classes][StdWndProc][12723]

The allocation number was: 1282

The block was previously freed by thread 0x15C8, and the stack trace (return addresses) at the time was:
403242 [System.pas][System][@FreeMem][3457]
476A61 [Controls.pas][Controls][TControl.Click][6758]
47AA44 [Controls.pas][Controls][TWinControl.WndProc][9336]
451761 [StdCtrls.pas][StdCtrls][TButtonControl.WndProc][4269]
47AB94 [Controls.pas][Controls][DoControlMsg][9405]
47AA44 [Controls.pas][Controls][TWinControl.WndProc][9336]
48DFC1 [Forms.pas][Forms][TCustomForm.WndProc][3902]
47A15B [Controls.pas][Controls][TWinControl.MainWndProc][9065]
42D99E [Classes.pas][Classes][StdWndProc][12723]
76EDF8D2 [Unknown function at GetMessageW]
76EDF794 [Unknown function at GetWindowLongW]

The current thread ID is 0x15C8, and the stack trace (return addresses) leading to this error is:
40C452 [FastMM4.pas][System][InternalScanMemoryPool][6858]
40C529 [FastMM4.pas][System][ScanMemoryPoolForCorruptions][6932]
5275A0 [Unit2.pas][Unit2][TForm1.Button1Click][47]
476A61 [Controls.pas][Controls][TControl.Click][6758]
47AA44 [Controls.pas][Controls][TWinControl.WndProc][9336]
451761 [StdCtrls.pas][StdCtrls][TButtonControl.WndProc][4269]
47AB94 [Controls.pas][Controls][DoControlMsg][9405]
47AA44 [Controls.pas][Controls][TWinControl.WndProc][9336]
48DFC1 [Forms.pas][Forms][TCustomForm.WndProc][3902]
47A15B [Controls.pas][Controls][TWinControl.MainWndProc][9065]
42D99E [Classes.pas][Classes][StdWndProc][12723]

Current memory dump of 256 bytes starting at pointer address 7FEBC0A0:
44 91 53 00 37 94 53 00 38 94 53 00 38 94 53 00 38 94 53 00 38 94 53 00 38 94 53 00 38 94 53 00
38 94 53 00 21 80 A3 8C 00 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
A7 3F 00 00 26 32 40 00 4E BD 4C 00 84 CC 4D 00 83 04 4D 00 F0 12 4D 00 83 04 4D 00 F0 12 4D 00
83 04 4D 00 9E 2E 4E 00 1A 5A 4D 00 7E 75 52 00 C8 15 00 00 42 32 40 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C8 15 00 00 20 00 00 00 B0 36 50 00 B0 82 C6 83 44 91 53 00 38 94 53 00 38 94 53 00 38 94 53 00
38 94 53 00 38 94 53 00 38 94 53 00 38 94 53 00 4F 7D 39 7C 38 94 53 00 00 00 00 00 A1 AF EB 7F
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 CA 04 00 00 22 C2 40 00 63 32 40 00 43 75 52 00
D ‘ S . 7 ” S . 8 ” S . 8 ” S . 8 ” S . 8 ” S . 8 ” S . 8 ” S .
8 ” S . ! € £ Œ . . . . . . . . . . . . . . . . . . . . . . . .
§ ? . . & 2 @ . N ½ L . „ Ì M . ƒ . M . ð . M . ƒ . M . ð . M .
ƒ . M . ž . N . . Z M . ~ u R . È . . . B 2 @ . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
È . . . . . . ° 6 P . ° ‚ Æ ƒ D ‘ S . 8 ” S . 8 ” S . 8 ” S .
8 ” S . 8 ” S . 8 ” S . 8 ” S . O } 9 | 8 ” S . . . . . ¡ ¯ ë 
. . . . . . . . . . . . . . . . Ê . . . " Â @ . c 2 @ . C u R .
Ich sitze schon mit AQtime6 (Line-Parsing geht leider nicht mit FastMM4 im FullDebug und D2009), WinDbg und AppVerifier (Handle detected) und der !HTrace-Fkt. dran.

Leider komme ich nicht voran.

Hat jemand Ideen?

Nachtrag 1:

Zumindest ein Problem scheint es in HtmlSubs.pas zu geben. Im Kontruktor der TSectionList.CreateCopy wird
Delphi-Quellcode:
  System.Move(T.ShowImages, ShowImages, DWord(@Background) - Dword(@ShowImages) + Sizeof(integer));
aufgerufen. Dies wird von FastMM innerhalb der .Print Routine bemängelt.

Gruß Assertor

Lasse2002 10. Dez 2008 13:43

Re: Leak im THtmlViewer finden
 
PreFontName: string; war mal ein ShortString bzw. string[lf_FaceSize+1]. Jetzt wird der string inkl reference count per move kopiert. Das kann nicht gutgehen.

Assertor 10. Dez 2008 13:57

Re: Leak im THtmlViewer finden
 
Hi Sebastian,

Danke für die Hilfe :)

Zitat:

Zitat von Lasse2002
PreFontName: string; war mal ein ShortString bzw. string[lf_FaceSize+1]. Jetzt wird der string inkl reference count per move kopiert. Das kann nicht gutgehen.

:)

Ich sitze auch gerade vor den ganzen System.Move(). Meine Meinung: Alle raus, zumindest außerhalb der GIF/PNG/ZLIB Fkt.

Sobald ich obiges mit einer Zuweisung ersetze, gibt es dort auch keine Fehler mehr:
Delphi-Quellcode:
constructor TSectionList.CreateCopy(T: TSectionList);
begin
...
inherited CreateCopy(Self, T);
// System.Move(T.ShowImages, ShowImages, DWord(@Background) - DWord(@ShowImages) + Sizeof(Integer));
ShowImages := T.ShowImages;
...
end;
Da hat Baldwin die Rechnung ohne die Größe der Datentypen gemacht.

Übrigens: Das Handle Leak entsteht auch irgendwo im Funktionsablauf von .Print. Soviel weiß ich jetzt schon, aber selbst ein Breakpoint auf die Adresse führt zu nichts.

Gruß Assertor

Assertor 19. Jan 2009 22:19

Re: Leak im THtmlViewer finden
 
Hi,

nach langer Suche steht nun fest: das Leak ist nicht aus der THtmlView Komponente, sondern aus Printers.pas.

Das Codeschnippsel
Delphi-Quellcode:
procedure TestPrinter;
var
  i: Integer;
begin
  for i := 1 to 100 do
  begin
    Printer.BeginDoc;
    Printer.EndDoc;
  end;
end;
zeigt das Problem ganz offensichtlich (in D2009 und D2006).

Ich mach hierzu dann einen neuen Thread auf.

Gruß Assertor


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:09 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz