Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   Debugger hält beim Programmende in CPU-Fenster (https://www.delphipraxis.net/202649-debugger-haelt-beim-programmende-cpu-fenster.html)

Codehunter 25. Nov 2019 07:25

Debugger hält beim Programmende in CPU-Fenster
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo!

Ich habe das Problem, dass seit einiger Zeit eines meiner Programme beim Beenden in der IDE das CPU-Fenster öffnet und dort an einem "Geister-Breakpoint" hält, jedoch keine Exception wirft. Siehe Bild unten. Vielleicht können die Experten da was rauslesen, ich habs jedoch nicht so mit Assembler.

Bei Recherche hier und mit dem Gockel habe ich Hinweise gefunden, die .DCU- und .DSK-Dateien zu löschen. Hat nichts geändert. An anderer Stelle wurde auf Non-ASCII-Zeichen im Pascalquellcode hingewiesen, doch laut Suchen-In-Dateien mit NP++ und Regex
Code:
[^\x00-\x7F]+
gibts sowas im betreffenden Projekt auch nicht. Ebenso wenig konnte ich Non-Standard-Linebreaks (!== $0C$0A) im Source finden.

Im unteren Teil sieht man Einträge wie "TInstItem.TBucketArray" und "FInstance", "FLock" und "FBuckets". Das konnte ich in der System.pas verorten. Allerdings auch dort weder Breakpoints gesetzt noch irgendwelche Sonderzeichen. Und nu mit dem Latein am Ende.

Grüße
Cody

TiGü 26. Nov 2019 09:36

AW: Debugger hält beim Programmende in CPU-Fenster
 
Delphi-Quellcode:
...
{$IFDEF USE_LIBICU}
  LibICUSuffix := '';
{$ENDIF}
{$IFDEF WEAKREF}
  InstHashMap.Finalize; // <---- Ersten Breakpoint drauf!
{$ENDIF}

{$IF defined(MSWINDOWS) or defined(OSX32)}
  {Uninitialize the default memory manager, and free all memory allocated by
   this memory manager.}
  FinalizeMemoryManager; // <---- Zweiten Breakpoint drauf!
{$ENDIF}
end.
Gehe mal in der System.pas gaaaanz runter bis zum finalization und kloppe mal die Breakpoints wie oben beschreiben rein und beende dein Programm ganz normal.
Wird der erste Breakpoint angesprungen und das CPU-Fenster ist noch nicht offen -> F9.
Geht dann vor dem zweiten Breakpoint das CPU-Fenster auf, dann alles nochmal auf Anfang!

Beim nächsten Beenden bis zum bitteren Erbrechen TInstHashMap.Finalize und die einzelnen TInstBucket.Finalize sowie TInstItem.Free Einträge durchsteppen und mit schlauen Hingucken den Übeltäter identifizieren.
Tritt das Problem immer bei den gleichen Indizes der Schleifen auf?
Immer weiter eingrenzen, irgendwo findest du dann den Übeltäter und kannst die Ursache dingfest machen!


Zusatzfrage: Bei dem Kollegen tritt das auch auf?

Codehunter 26. Nov 2019 09:58

AW: Debugger hält beim Programmende in CPU-Fenster
 
Das Problem tritt offensichtlich noch vor dem
Delphi-Quellcode:
InstHashMap.Finalize
auf. Ja sogar noch bevor der finalization-Abschnitt in der System.pas überhaupt begonnen wird.

Irgendwo fand ich auch den Hinweis, dass sowas gerne mal durch vergessene Breakpoints in externen (Microsoft-) DLLs verursacht wird. Da hat doch nicht etwa das Windows-Update irgendwas...???

EDIT: Das letzte das in der System.pas aufgerufen wird bevor das CPU-Fenster aufgeht ist
Delphi-Quellcode:
FinalizeUnits
EDIT2: Du hast mich da auf eine Spur gebracht. Innerhalb der FinalizeUnits-Prozedur gibt es eine Schleife
Delphi-Quellcode:
while Count > 0 do
welche reproduzierbar bis Count=506 funktionierte. Ab da krachte es in der darauf folgenden Zeile
Delphi-Quellcode:
TProc(P)();
. Diese mit F7 angesprungen versandete im finalization-Abschnitt der SynEdit.pas. Das grenzt die Sache schon etwas ein.

Codehunter 26. Nov 2019 11:07

AW: Debugger hält beim Programmende in CPU-Fenster
 
So, jetzt bin ich mit viel F7 bis zur wirklich letzten Zeile gekommen, die dann im CPU-Fenster endet:
Delphi-Quellcode:
CALL   DWORD PTR [EAX] + VMTOFFSET IInterface._Release
in der System.pas:_IntfClear-Function. Weiter komme ich mit meinem Latein nun nicht mehr. Demnach soll ein Interface freigegeben werden. Nur welches?

TiGü 26. Nov 2019 11:31

AW: Debugger hält beim Programmende in CPU-Fenster
 
Kannst du das Argument Dest: IInterface in _IntfClear auf ein TInterfacedObject casten und bei Erforlg dir den TInterfacedObject(Dest).Classtype bzw .Classname ausgeben lassen?

Codehunter 26. Nov 2019 11:45

AW: Debugger hält beim Programmende in CPU-Fenster
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von TiGü (Beitrag 1452172)
Kannst du das Argument Dest: IInterface in _IntfClear auf ein TInterfacedObject casten und bei Erforlg dir den TInterfacedObject(Dest).Classtype bzw .Classname ausgeben lassen?

Spannende Frage! So wie die Implementierung von _IntfClear aussieht mit dem Assembler, wüsste ich erstmal nicht wie. Zumal die System.pas an sich ja nicht wirklich editierbar ist.

Via STRG+F7 wird gesagt, TInterfacedObject(Dest) wäre Nil.

EDIT: Dest ist nur zu Beginn der Prozedur Nil. Unmittelbar vor dem IInterface._Release ist sie gesetzt, jedoch nicht zugreifbar (E2171 Auf Variable 'Dest' kann wegen Optimierung nicht zugegriffen werden). Ein {$O-} änderte daran nichts :(

hoika 26. Nov 2019 12:16

AW: Debugger hält beim Programmende in CPU-Fenster
 
Hallo,
das hatte ich auch mal.
Kam vom unsauberen Mischen von Interfaces und Objekten.
Dabei wurde das Objekt bereits zerstört, das Interface bekam es aber nicht mit und wollte es noch ml zerstören.
Nun ja, etwas vereinfacht ;)

Lösung war mühselig:
Ausklammern aller Units, laufen lassen
erste Unit rein, laufen lassen

Lösung war dann, unsere Interface-Variablen immer vor dem Verlassen des Scopes explizit auf nil zu setzen.
Vielleicht übergibst Du auch irgendwo ein Interface als Parameter ohne das const.

Du glaubst zu wissen, das es was mit SynEdit zu tun hat.
Kann sein, muss aber nicht.

Viel Erfolg!

Codehunter 26. Nov 2019 12:25

AW: Debugger hält beim Programmende in CPU-Fenster
 
Zitat:

Zitat von hoika (Beitrag 1452180)
Du glaubst zu wissen, das es was mit SynEdit zu tun hat.
Kann sein, muss aber nicht.

Genau das ist der Punkt. Mehr wie ein Anhaltspunkt ist das nicht, dass er zuletzt im finalization von SynEdit ist. Das Dilemma an der Sache: Ich selbt arbeite in KEINER von meinen Units mit Interfaces. Wenn dann höchstens indirekt mit eingebundenen Komponenten. Weil das Projekt aber laut MMX aus 183 Units (ohne RTL und VCL!) besteht, bin ich da wohl Wochen beschäftigt. :(

hoika 26. Nov 2019 15:09

AW: Debugger hält beim Programmende in CPU-Fenster
 
Hallo,
Zitat:

Ich selbst arbeite in KEINER von meinen Units mit Interfaces.
Ah so, das ist doof ;(

Sind viele Units in deiner DPR? -> alles raus, dann schrittweise rein
Weißt Du, ab wann das auftrat -> alte Version zurückspielen.

Codehunter 27. Nov 2019 07:32

AW: Debugger hält beim Programmende in CPU-Fenster
 
Ich werd noch wahnsinnig :evil:

Es sieht so aus als wäre es mein altes Problem mit der Virtualmachine, nur in neuerer Fehlersymptomatik. An den VM-Einstellungen gedreht, weg ist der Fehler.

MyRealName 27. Nov 2019 07:46

AW: Debugger hält beim Programmende in CPU-Fenster
 
SynEdit hat da ein Problem, weil ich habe an einer Stelle in einer Anwendung SynEdit wegen eines Custom-SQL-Editors im Programm für unsere User. Rufe ich das nicht auf, schließt sich das Programm sauber, öffne ich das Fenster mit dem SynEdit Memo auch nur einmal, dann kriege ich beim Schließen der Anwendung einen Fehler im der was mit einem Interface in SynEdit zu tun hat.

Codehunter 27. Nov 2019 08:40

AW: Debugger hält beim Programmende in CPU-Fenster
 
Das kann gut sein dass sich da gegenseitig was aufschaukelt. Denn den SynEdit in Verbindung mit dem SQL-Highlighter verwende ich auch.

Codehunter 13. Dez 2019 10:23

AW: Debugger hält beim Programmende in CPU-Fenster
 
So, wo ich mal wieder Zeit hatte konnte ich das Problem reproduzieren und eingrenzen. Und zwar liegt es am VirtualBox Grafikkartentreiber. Wenn man in den VBox-Einstellungen die Grafikkarte auf VBoxSVGA stellt und den 3D-Support aktiviert, dann wirft SynEdit solche Exceptions. Das kann man mit einem Workaround beheben, indem man in der SynEdit.inc ganz am Ende den DirectWrite-Support auskommentiert:
Delphi-Quellcode:
// DirectWrite
{$IFDEF SYN_DELPHI_XE2_UP}
  //{$DEFINE SYN_DirectWrite}
{$ENDIF}
Dann noch das Synedit-Package neu erzeugen und fertig. Damit habe ich zwar die genaue Ursache noch nicht gefunden, aber zumindest gibts keine Exceptions mehr. Der Nachteil ist, dass Synedit dann wieder GDI zeichnet und entsprechend etwas langsamer ist.

MyRealName 13. Dez 2019 10:38

AW: Debugger hält beim Programmende in CPU-Fenster
 
Das ist seltsam, weil ich nutze keine VM und habe das Problem, aber ich kann es mal probieren dieses WE.

Codehunter 13. Dez 2019 10:51

AW: Debugger hält beim Programmende in CPU-Fenster
 
Zitat:

Zitat von MyRealName (Beitrag 1453393)
Das ist seltsam, weil ich nutze keine VM und habe das Problem, aber ich kann es mal probieren dieses WE.

Naja, das hat evtl. auch nur bedingt etwas mit der VM zu tun. Hier kann man den 3D-Support einfach ein- und ausschalten. Bei "echten" Grafikkarten ist der ja immer an. Möglicherweise fällt Windows automatisch auf GDI zurück, wenn man versucht auf einem Non-3D-System per DirectWrite zu zeichnen. Dann würde der Fehler nicht auftreten und demzufolge erklärt sich auch, warum bei mir keine Exceptions mehr kamen als ich auf VBoxVGA (nicht VBoxSVGA) ohne 3D umgeschaltet habe.

Codehunter 13. Dez 2019 11:11

AW: Debugger hält beim Programmende in CPU-Fenster
 
Nachtrag: Ursache gefunden!

In der SynEdit.pas in der function TCustomSynEdit.CreateD2DCanvas folgende Zeile suchen:
Delphi-Quellcode:
    HR := D2DFactory.CreateHwndRenderTarget(D2D1RenderTargetProperties,
      D2D1HwndRenderTargetProperties(Handle, Size), FRenderTarget);
und wie folgt ergänzen:
Delphi-Quellcode:
    HR := D2DFactory.CreateHwndRenderTarget(D2D1RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_SOFTWARE),
      D2D1HwndRenderTargetProperties(Handle, Size), FRenderTarget);,
Das scheint also wirklich ein Treiberproblem zu sein. Denn laut MSDN heißt es
Zitat:

Zitat von MSDN
The render target uses hardware rendering, if available; otherwise, it uses software rendering.

Wenn ich nun explizit D2D1_RENDER_TARGET_TYPE_HARDWARE angebe, bekomme ich genau die selben Exceptions. Erzwinge ich Software-Rendering (D2D1_RENDER_TARGET_TYPE_SOFTWARE), dann funktioniert es. Scheinbar melden manche Treiber inkorrekterweise, sie könnten D2D-Hardware-Rendering, obwohl es nicht stimmt. Dadurch erfolgt das notwendige Fallback auf Software-Rendering nicht. Dann kracht es irgendwo in der GPU, wo der Debugger nicht mit kommt und nur noch ratlos das CPU-Fenster anzeigt. So erkläre ich mir das jedenfalls. Vielleicht findet sich ja hier jemand, der das Ganze etwas besser erklären kann.

Noch ein Nachtrag: Ich denke ich habe die Erklärung gefunden. Vor langer Zeit wurde das in SynEdit implementiert. Damals gab es damals nur DirectX9. Irgendwann kam DX10 und wurde in der Winapi.D2D1.pas ergänzt. Nur wurde SynEdit nie daran angepasst. So wie es in SynEdit implementiert ist, fällt die Initialisierung auf DX9-Featurelevel zurück. Manche Graka-Treiber bieten aber nur DX10. Man kann DX10 erzwingen, wenn man die oben genannte Zeile wie folgt ändert:
Delphi-Quellcode:
HR := D2DFactory.CreateHwndRenderTarget(
  D2D1RenderTargetProperties(
    D2D1_RENDER_TARGET_TYPE_DEFAULT,
    D2D1PixelFormat(),
    0, 0,
    D2D1_RENDER_TARGET_USAGE_NONE,
    D2D1_FEATURE_LEVEL_10
  ),
  D2D1HwndRenderTargetProperties(Handle, Size), FRenderTarget
);
Entscheidend ist D2D1_FEATURE_LEVEL_10 anzugeben, wenn man ein DX10-System hat und D2D1_FEATURE_LEVEL_9 wenn man ein DX9-System hat. Jetzt habe ich aber spontan nichts gescheites gefunden, wie man die DirectX-Version ermitteln könnte. Außer in der Registry rumzustöbern.

TiGü 13. Dez 2019 13:54

AW: Debugger hält beim Programmende in CPU-Fenster
 
Zitat:

Zitat von Codehunter (Beitrag 1453398)
Jetzt habe ich aber spontan nichts gescheites gefunden, wie man die DirectX-Version ermitteln könnte. Außer in der Registry rumzustöbern.

https://www.delphipraxis.net/179042-...t2d-1-1-a.html

D3D11CreateDevice -> Array mit gewünschten Feature Levels reingeben, das höchste unterstützte wird mit zurückgeben. Wenn größer gleich D3D_FEATURE_LEVEL_10_0, dann
kannst du von D2D1_FEATURE_LEVEL_10 ausgehen.

Beispiel:

Delphi-Quellcode:
function TDirectXBase.CreateD3DResources : Boolean;
var
  LD3DDevice : ID3D11Device;
  LCreationFlags : Cardinal;
  LD3DDeviceContext : ID3D11DeviceContext;
  LDriver : D3D_DRIVER_TYPE;
  SupportedFeatureLevel: D3D_FEATURE_LEVEL;
const
  FeatureLevels : array [0 .. 6] of D3D_FEATURE_LEVEL = (
    D3D_FEATURE_LEVEL_11_1,
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0,
    D3D_FEATURE_LEVEL_9_3,
    D3D_FEATURE_LEVEL_9_2,
    D3D_FEATURE_LEVEL_9_1);
  DriverTypes : set of D3D_DRIVER_TYPE = [D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_WARP];
begin
  Result := False;
  LCreationFlags := LongWord(D3D11_CREATE_DEVICE_BGRA_SUPPORT);
  {$IFDEF DEBUG}
  LCreationFlags := LCreationFlags or LongWord(D3D11_CREATE_DEVICE_DEBUG);
  {$ENDIF}

  for LDriver in DriverTypes do
  begin
    Result := Succeeded(D3D11CreateDevice(nil, LDriver, 0, LCreationFlags, @FeatureLevels, Length(FeatureLevels), D3D11_SDK_VERSION, LD3DDevice, @SupportedFeatureLevel, LD3DDeviceContext));
    if Result then
      Break;
  end;

// hier dann was mit SupportedFeatureLevel machen

end;

TurboMagic 13. Dez 2019 19:08

AW: Debugger hält beim Programmende in CPU-Fenster
 
Wie bekommen wir diese Verbesserungen in das offizielle SynEdit rein?
Damit alle profitieren und nicht jeder solche Fixes selber anbringen
muss!

Codehunter 13. Dez 2019 20:00

AW: Debugger hält beim Programmende in CPU-Fenster
 
Welches ist denn das "offizielle" SynEdit? Davon gibt es doch inzwischen so viele Forks... Die DirectDraw-Version konnte ich jetzt nicht mal in einem Repository finden. Wir haben diese Variante seit 2018 im Projekt. Die Probleme kamen in meinem Fall nach einem VBox-Update auf. Die Version die man aktuell bei Github findet, ist ein Fork vom einem Zweig, den ich selbst vor 7 Jahren bei Sourceforge gepflegt habe - wie man an der Signatur im Header erkennen kann. Die Variante mit DirectDraw ist auch ein Fork von "meinem" Zweig damals, jedoch nicht mit der Github-Version verwandt. Die Jungs bei Lazarus/LCL pflegen wiederum eine Variante, die noch vor meinem Zweig von der Urversion von Mael Hörz abgeleitet wurde. Alles sehr verworren mittlerweile. :lol:

TurboMagic 14. Dez 2019 08:49

AW: Debugger hält beim Programmende in CPU-Fenster
 
Welches ist denn das SynEdit Paket, das per GetIt installierbar ist?
Das würde ich wohl als das einigermaßen offizielle ansehen.

Es gibt diverse verweiste Sachen bei denen es schön wäre, wenn diese
weiter gepflegt würden. Nur wie bekommen wir sowas koordiniert hin
um es

a) überhaupt zu tun
b) Doppelarbeiten zu vermeiden?

Grüße
TurboMagic

Uwe Raabe 14. Dez 2019 10:44

AW: Debugger hält beim Programmende in CPU-Fenster
 
Zitat:

Zitat von TurboMagic (Beitrag 1453440)
Welches ist denn das SynEdit Paket, das per GetIt installierbar ist?

Ich vermute https://github.com/TurboPack/SynEdit

Codehunter 16. Dez 2019 06:22

AW: Debugger hält beim Programmende in CPU-Fenster
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1453442)
Zitat:

Zitat von TurboMagic (Beitrag 1453440)
Welches ist denn das SynEdit Paket, das per GetIt installierbar ist?

Ich vermute https://github.com/TurboPack/SynEdit

Da wird kein DirectWrite verwendet. Ich finde das Ganze auch sehr verwirrend, weil ich nicht nachvollziehen kann woher diese Variante mit DirectWrite gekommen ist. Ich habe sie inzwischen in verschiedenen Projekten gefunden, aber weder auf Github noch auf SF konnte ich in den Logs Hinweise finden dass es irgendwann mal einen entsprechenden Patch gegeben hätte. Die DirectWrite-Variante enthält aber meine Signatur, daher muss sie von der SF-Variante abstammen. Gleiches gilt für die von dir verlinkte Turbopack-Variante.

Ich frage mich ohnehin ob die Verwendung von DirectWrite nun sooo sinnvoll ist. Das verhindert doch z.B. die Verwendung mit CrossVCL unter Linux oder MacOS. Nennenswerte Performanceunterschiede konnte ich zumindest nicht feststellen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:44 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