Autor |
Beitrag |
HenryHux
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 10.12.10 13:48
Hi,
in meinem Bilderkennungsprogramm bekomme ich nach einer längeren Laufzeit (>20 Min) den o.g Fehler.
Ich bekomme nicht mehr Informationen vom Debugger als die Meldung ungültiges Handle und er zeigt immer auf verschiedene Befehle, die rein garnichts mit Handles zu tun haben.
Insofern habe ich leider keine Idee wodran das liegen könnte.
Der Quelltext ist viel zu lang als das ich ihn einfach posten könnte, deshalb wollte ich mal fragen, ob ihr eventuell einen Verdacht habt.
Handles benutze ich aber in folgenden Funktionen:
Einmal als sleep Alternative, dürfte eigentlich keine Probleme machen :
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| procedure wait(Milliseconds: Integer); var Tick: DWORD; Event: THandle; begin Event := CreateEvent(nil, False, False, nil); try Tick := GetTickCount + DWORD(Milliseconds); while (Milliseconds > 0) and (MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do begin Application.ProcessMessages; Milliseconds := Tick - GetTickCount; end; finally CloseHandle(Event); end; end; |
Und einmal als Screenshot Funktion, dadran könnte es liegen, da sie immer mit verschiedenen Parametern aufgerufen wird, aber auch die zeit nach 10k durchläufen keine Fehlermeldung:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33:
| function Screenshot(Bounds:TRect; Links, Rechts, Oben, Unten : Integer) : tbitmap; inline; var DeskCanvas: TCanvas; ShotTargetBitmap : TBitmap; Cut : TRect; begin result:=TBitmap.Create; bounds.left:=bounds.Left+verschiebenx; bounds.right:=bounds.right+verschiebenx; bounds.top:=bounds.top+verschiebeny; bounds.bottom:=bounds.bottom+verschiebeny; try DeskCanvas := TCanvas.Create; DeskCanvas.Handle := GetDC(0); Shottargetbitmap:=TBitmap.create; try ShotTargetbitmap.Width := Round((Bounds.Right - Bounds.left) * 1); ShotTargetbitmap.Height := Round((Bounds.Right - Bounds.Left) * 1); BitBlt(ShotTargetBitmap.Canvas.Handle, 0 ,0, bounds.Right-bounds.left, bounds.Bottom-bounds.top, DeskCanvas.handle, bounds.Left, bounds.Top, SRCCOPY); Cut.Left := Links; Cut.Top := Oben; Cut.Right := Rechts; Cut.Bottom := Unten; result.Width := Cut.Right - Cut.Left; result.Height := Cut.Bottom - Cut.Top; BitBlt(result.Canvas.Handle, 0, 0, Cut.Right, Cut.Bottom, ShotTargetBitmap.Canvas.Handle, Cut.Left, Cut.Top, SRCCOPY); finally ReleaseDC(0,DeskCanvas.Handle); end; finally FreeAndNil(deskcanvas); FreeAndNil(ShotTargetBitmap); end; end; |
Wie gesagt, ich habe keine Idee was da schief läuft, vlt fällt euch ja was ein.
Lg
Henry
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 10.12.10 15:02
Das hört sich nach einem Problem mit Threads an. Und zwar verwendest du da vermutlich irgendwelche visuellen Komponenten oder Klassen, die einen DC benutzen, z.B. TBitmap.
|
|
HenryHux 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 10.12.10 15:24
Hmm und was könnte das sein?
Threads habe ich keine, ohne Klassen kommt das Problem auch nicht.
Visuelle Komponenten sind auch keine drin außer labels.
Und die einzige Funktion die ein DC benutzt ist die Screenshot Funktion, die ich schon gepostet hab.
Wenn man das Problem nicht genauer lokalisieren kann, kann ichs einfach irgendwie ignorieren?
Lg
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 10.12.10 15:36
Kann es sein, dass du die erzeugte Bitmap, die du zurückgibst (äußerst schlechter Stil...  ), nicht wieder freigibst? Dann hat dein Programm einfach zu viele GDI-Handles...
Schau einmal nach deren Anzahl im Taskmanager / Process Explorer.
|
|
HenryHux 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 10.12.10 15:57
Okay, das wird ein Problem sein, dass ich die nicht wieder freigebe.
Wie kann ich denn den Rückgabewert von Funktionen nach Abschluss der Funktion löschen oder was wäre ein besserer Stil?
Dachte mir, das würde so am saubersten gehen, denn dann kann der Aufruf einer anderen Funktion ja einfach so aussehen:
Delphi-Quelltext 1: 2: 3: 4:
| ComparePicture:= Tbitmap.create; ComparePicture.LoadFromFile(Path+'Ordner2\'+'bsp.bmp'); result := CompareImages(Screenshot(Rect(sittingoutlinks,sittingoutoben,sittingoutlinks + 100,sittingoutoben + 100),20,100,85,100), ComparePicture); |
Wenn ich eine globale Bitmap benutze gäbe das keine Probleme?
Lg
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 10.12.10 16:01
Übergib die (vorher erzeugt, wenn es sein muss als Feld der Klasse im Konstruktor) als Parameter und gib die danach wieder frei. Das ist die einzige wirklich saubere Lösung.
|
|
HenryHux 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 10.12.10 16:19
Ok, nochmal zum Verständnis, ob ich dich richtig verstanden habe.
Angenommen ich mach ne neue TBitmap var, nennen wir die TBmp.
Die Create ich in der Screenshot Funktion und .Free sie bei nem except.
Dann rufe ich die Funktion auf in ner anderen Prozedur und arbeite mit der TBmp und .Free die dann auf finally.
Ist das also so io?
Das einzige was passieren könnte ist, dass er in der Funktion einen except bekommt die Variable auflöst und eine andere Prozedur versucht mit der zu arbeiten und auch abstürzt weil die versucht die aufzulösen?
LG
|
|
Gerd Kayser
      
Beiträge: 632
Erhaltene Danke: 121
Win 7 32-bit
Delphi 2006/XE
|
Verfasst: Fr 10.12.10 17:51
|
|
HenryHux 
      
Beiträge: 542
Erhaltene Danke: 33
Windows 7 Premium
Delphi XE, Eclipse
|
Verfasst: Fr 10.12.10 18:34
Ich weiß nicht, was es genau war aber nachdem ich die Bitmaps nicht als Rückgabewert übergebe, klappt es (vorerst).
FastMM4 zeigt mir jetzt auch keine Leaks mehr an.
Danke!
Lg
|
|
jaenicke
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 11.12.10 01:39
Und dann hier auch noch eine saubere Variante (gekürzt), falls du es noch nicht so hast: Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| function CreateSnapshot(AWindow: HWND; ATarget: TBitmap): Boolean; var DesktopDC: HDC; begin Result := False; DesktopDC := GetDC(AWindow); try ... Result := True; finally ReleaseDC... end; end;
var MySnapshot; TBitmap; begin MySnapshot := TBitmap.Create; try if CreateSnapshot(0, MySnapshot) then WorkWithMySnapshot... else finally MySnapshot.Free; end; end; |
|
|
|