Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.166 Beiträge
 
Delphi 12 Athens
 
#1

welches Ereignis wenn Package geladen/entladen?

  Alt 2. Feb 2021, 13:26
Moin Moin,

im Zuge einer Fehlersuche nach langjährig versteckten Fehlern (z.B. globale Variable nach Objektfreigabe nicht genilt),
wollte ich endlich mal ein Logging einbauen.

Vor allem wenn ein Designtime-Package compiliert wird und daher alle Abhängigen ent-/geladen werden, da knallt es ab und an gern Mal.
Leider erst später in den Tiefen der delphi-eigenen IDE-Packages, wo man mit dem Stacktrace nichts mehr anfangen kann.
Auch ist es unmöglich die Adresse des "defekten" Objektzeigers zu bekommen, um den mit vorher bekannten Objekten vergleichen zu können, weil z.B. beim Free/Destroy/FreeMem die Parameter in den Registern liegen und daher schon lange überschrieben wurden, nachdem/sobald es knallte.


Mein Problem ist nun, wie/wo ich das Logging, am Besten "einheitlich", in alle unsere Packages/DLLs einfügen kann.

Bei EXE und DLL gibt es den Entry-Point von Windows (BEGIN in der DPR, was der main-Funktion vom C++ entspricht)
und man kann sich bei der ExitProc registrieren, für das Unload.

Eine BPL ist eigentlich auch nur DLL, mit paar Extras, aber dort fehlt die Main-Function in der DPK.



Der erste einfache Gedanke war eine kleine Unit, welche als Erstes im CONTAINS steht,
aber deren Code wird niemals ausgeführt.

Selbst wenn ich diese Unit auch noch ins USES von anderen Units einbinde, welche später definitiv geladen/genutzt werden.

Delphi-Quellcode:
unit SysDB_Init;

interface

implementation

{$IFDEF WINDOWS}
uses
  Winapi.Windows;

(*type
  IOTACustomMessage = interface(IUnknown)
  end;
  IOTAMessageServices40 = interface(IUnknown)
    ['{26EB0E4E-F97B-11D1-AB27-00C04FB16FB3}']
    procedure AddCustomMessage(const CustomMsg: IOTACustomMessage);
    procedure AddTitleMessage(const MessageStr: string);
    procedure AddToolMessage(const FileName, MessageStr, PrefixStr: string; LineNumber, ColumnNumber: Integer);
    procedure ClearAllMessages;
    procedure ClearCompilerMessages;
    procedure ClearSearchMessages;
    procedure ClearToolMessages;
  end;*)


initialization
  //OutputDebugString('LOAD SysDB');
  MessageBox(0, 'LOAD SysDB', '', 0);

  {var H := GetModuleHandle(PChar(Format('designide%d.bpl', 'IDEVersion'));
  if A <> 0 then begin
    var P := GetProcAddress('@Toolsapi@BorlandIDEServices');
    if P <> nil then begin
      I := P^;
      if I <> nil then
        //(I as IOTAMessageServices40).AddTitleMessage('Message');
        (I as IOTAMessageServices40).AddToolMessage('Filename', 'Message', 'Prefix', 11, 22);
    end;
  end;}


finalization
  //OutputDebugString('UNLOAD SysDB'); // im Programm
  MessageBox(0, 'UNLOAD SysDB', '', 0); // in IDE (eigentlich via IOTAMessageServices40.AddToolMessage)

{$ENDIF}

end.
(Nicht wundern, das ist ein Runtime-Package, welches aber auch in der IDE als Abhängigkeit geladen wird ... aber im eigentlichen Programm darf natürlich die DesignIde-BPL nicht geladen werden ... drum ist die auch nicht hart verlinkt und ich hole mir die Logfunktion für's Compiler-Log manuell raus)


Wie ist es nun möglich, dass ich beim Load und Unload dieses/unserer Package(s) mein Logging immer "sicher" durchführen kann, sowie z.B. beim Create/Destroy der der enthaltenen DatenModule. (Letzteres geht einfach)


Automatisch geladenen (via REQUIRED verlinkt) werden nicht alle Units initialisiert.
Beim manuellen Laden via LoadPackage wird die exportierte Funktion "finalize" ausgeführt, in welcher scheinbar alle Units initialisiert werden. (aber das machen wird nicht)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu ( 2. Feb 2021 um 13:31 Uhr)
  Mit Zitat antworten Zitat