Important Note: Leaks checking happens at a very special moment in your application: everything is already dead (finalized). Be sure to review your handler's code, so it will not access any globals, because these will be already finalized when leaks checking is running. Write code very carefully, don't forget that your whole application is basically already dead. This includes even most basic routines from the SysUtils unit! E.g. even a simple Format may fail, because FormatSettings is already finalized. Definitely no throwing exceptions at this point!
Since leaks checking is such a special place - your typical event handlers will not run, as people usually write handler's code without such strict restrictions. However, you still can register event handler for leaks checking. You just need to (re-)register your event handlers during leaks checks. For example:
uses
EException, // for TEurekaExceptionInfo
EEvents, // for RegisterEventXYZ
ETypes; // for MemLeaksShow
// Your event handlers
// It is just an example
procedure YourHandler1
(const ACustom: Pointer;
AExceptionInfo: TEurekaExceptionInfo;
var AHandle: Boolean;
var ACallNextHandler: Boolean);
begin
// ...
end;
procedure YourHandler2
(const ACustom: Pointer;
AExceptionInfo: TEurekaExceptionInfo;
const AEurekaAction: TEurekaActionType;
const AAdditionalInfo: String;
var AExecute: Boolean;
var ACallNextHandler: Boolean);
begin
// Just an example
if AEurekaAction = atShowingExceptionInfo then
begin
// ...
end;
end;
var
// Default EurekaLog's code to show/process leaks
ShowMemLeaks: TMemLeaksProc;
// Asks EurekaLog to call our event handler for leaks
procedure AssignEventHandlersForLeaks;
begin
// Registers the handlers
RegisterEventExceptionNotify(nil, YourHandler1);
RegisterEventExceptionAction(nil, YourHandler2);
// ...
// Shows leaks
ShowMemLeaks;
end;
finalization
// Asks EurekaLog to call our code when leaks are found
ShowMemLeaks := MemLeaksShow;
MemLeaksShow := AssignEventHandlersForLeaks;
end.
Note: leaks checking is always run from the main thread and all background threads should already be finalized, so no synchronization is (usually) necessary.
You may even assign the same event handler for both your normal exceptions and for leaks! Just be sure that its code is safe to be run during leaks checking. If you want to distinguish between normal exceptions and leaks - you can use custom parameter. For example:
uses
EException, // for TEurekaExceptionInfo
EEvents, // for RegisterEventXYZ
ETypes; // for MemLeaksShow
const
// A special flag to indicate that
// code runs during leaks checking
// It could be anything
// It is just an example
CalledFromLeaks = Pointer(1);
// Your event handler
// It is just an example
procedure DoYourThing
(const ACustom: Pointer;
AExceptionInfo: TEurekaExceptionInfo;
var AHandle: Boolean;
var ACallNextHandler: Boolean);
var
Leaks: Boolean;
begin
// Are we being called during leaks checks?
Leaks := (ACustom = CalledFromLeaks);
// When called for normal exceptions -
// you may want to use synchronization
// to access some globals
if not Leaks then
// It is just an example
CriticalSection.Enter;
try
// Your code here
if Leaks then
begin
// Globals are already finalized,
// so you should not access them
end
else
begin
// You can access globals here
// We have already acquired sync obj
end;
finally
// It is just an example
if not Leaks then
CriticalSection.Leave;
end;
end;
var
// Default EurekaLog's code to show/process leaks
ShowMemLeaks: TMemLeaksProc;
// Asks EurekaLog to call our event handler for leaks
procedure AssignEventHandlersForLeaks;
begin
// Registers the handler for leaks
// Use the special flag to indicate that
// this happens during leaks checking
RegisterEventExceptionNotify(CalledFromLeaks, DoYourThing);
// Shows leaks
ShowMemLeaks;
end;
initialization
// Registers the handler for normal exceptions
// Do not use any flags
RegisterEventExceptionNotify(nil, DoYourThing);
finalization
// Asks EurekaLog to call our code when leaks are found
ShowMemLeaks := MemLeaksShow;
MemLeaksShow := AssignEventHandlersForLeaks;
end.
Alternatively, you may just use properties of AExceptionInfo:
// Are we being called during leaks checks?
Leaks := (AExceptionInfo.ExceptionClass = 'EMemoryLeak') or
(AExceptionInfo.ExceptionClass = 'EResourceLeak');
See also:
Send feedback...
|
Build date: 2024-09-30
Last edited: 2023-08-09
|
PRIVACY STATEMENT
The documentation team uses the feedback submitted to improve the EurekaLog documentation.
We do not use your e-mail address for any other purpose.
We will remove your e-mail address from our system after the issue you are reporting has been resolved.
While we are working to resolve this issue, we may send you an e-mail message to request more information about your feedback.
After the issues have been addressed, we may send you an email message to let you know that your feedback has been addressed.
Permanent link to this article: https://www.eurekalog.com/help/eurekalog/how_to_register_event_handler_for_leaks.php
|
|