It is in system.inc
Procedure fpc_assert(Const Msg,FName:Shortstring;LineNo:Longint;
ErrorAddr:Pointer); [Public,Alias : 'FPC_ASSERT']; compilerproc;
begin
if codepointer(AssertErrorProc)<>nil then
AssertErrorProc(Msg,FName,LineNo,ErrorAddr)
else
HandleErrorAddrFrameInd(227,get_pc_addr,get_frame);
end;
Mind that this is an intrinsic. As you can see the boolean result of the condition is not in the parameters => that code is inlined into your calling procedure. So the above is only called, if the condition fails.
Afaik it then depends. If any unit in your app (including recursively any unit you used) uses "SysUtils then it throws an exception.
And if you want you can catch that exception.
And as one might also conclude from that code: one can replace AssertErrorProc if one wants. For example the mentioned throwing of an exception is accomplished by the SysUtils unit setting AssertErrorProc in its initialization section.
Hi @PascalDragon. I am yet very new to all this and trying to teach myself how things work under the hood. So, The fpc_assert procedure checks whether a custom error handler (AssertErrorProc) is set? If it is, it uses it to handle the assertion. Otherwise, it uses a default handler (HandleErrorAddrFrameInd) ? Is that the way things work?
I also ran the code snippet above throughchatGPT as it has many times helped me to break down things and understand how the code works. This is what chatGPT said when I asked it to give me a heavily commented breakdown and explanation:
---
Procedure fpc_assert(Const Msg, FName: Shortstring; LineNo: Longint; ErrorAddr: Pointer);
// Declares the procedure 'fpc_assert', which is used to handle assertion errors.
// Parameters:
// - Msg: A message string that provides details about the assertion error.
// - FName: The name of the file in which the assertion failed.
// - LineNo: The line number in the file where the assertion failure occurred.
// - ErrorAddr: A pointer to the address where the error occurred, which can
// help in debugging the issue by showing the memory location.
[Public, Alias : 'FPC_ASSERT']; // The procedure is public and has an alias 'FPC_ASSERT'.
// This means it can be called using 'FPC_ASSERT' as an alternative name.
compilerproc; // This attribute specifies that it is a compiler-provided procedure
// and can only be used internally by the compiler.
begin
if codepointer(AssertErrorProc) <> nil then
// Check if 'AssertErrorProc' (a custom assertion error handler) is set.
// 'codepointer' is used to obtain the code pointer of 'AssertErrorProc' and check if it's not nil.
// If it's nil, no custom error handler is defined, so we use a default handler instead.
AssertErrorProc(Msg, FName, LineNo, ErrorAddr)
// If 'AssertErrorProc' is not nil, call it with the provided assertion details (Msg, FName, LineNo, ErrorAddr).
// This allows the custom handler to process the assertion failure as needed.
else
HandleErrorAddrFrameInd(227, get_pc_addr, get_frame);
// If 'AssertErrorProc' is nil, use the default error handler 'HandleErrorAddrFrameInd'.
// Parameters for 'HandleErrorAddrFrameInd':
// - 227: Likely a specific error code indicating an assertion failure.
// - get_pc_addr: Function to get the program counter (PC) address where the error occurred.
// - get_frame: Function to get the current stack frame, which helps in tracing the error context.
end;
It also gave me this:
Key Points Explained
Parameters:
Msg: A short string with the error message for the assertion. This message usually describes what the assertion expected to be true.
FName: The file name where the assertion failed, which aids in debugging by showing the source location.
LineNo: The line number in the file where the failure happened, which helps pinpoint the exact location in the source code.
ErrorAddr: The memory address where the error occurred, useful for lower-level debugging.
Error Handling Logic:
Custom Handler (AssertErrorProc):
AssertErrorProc is checked first. If it’s not nil, it means a custom error-handling procedure is set, and it will be used to handle the assertion.
This is useful if developers want to customize how assertions are reported or handled.
Default Handler (HandleErrorAddrFrameInd):
If AssertErrorProc is nil (no custom handler is provided), it falls back on a default handler, HandleErrorAddrFrameInd. This function uses
hardcoded values and system functions (get_pc_addr and get_frame) to identify the program counter and stack frame, aiding in debugging
by showing the context of the assertion failure.
This setup allows the fpc_assert procedure to either use custom handling or revert to a default approach, ensuring assertions are managed consistently,
even if a custom handler is absent.
Is the above correct? The reason I ask is when I run anything through chatGPT I usually get myself in a lot of trouble with the community or end up being told not to use generated AI nonsense. But to me, chatGPT is simply another 'tool' that has helped me understand code which at first was way over my head. I decided to share this in the hope if the breakdown is correct and accurate it can help others who are newbies like myself.