Diagnosing and Resolving EAccessViolation Errors in RAD Studio VCL Applications
Learn how to diagnose and fix EAccessViolation errors in RAD Studio VCL applications by identifying nil and dangling pointers using the integrated debugger and FastMM4.
26 Jul 2026, 17:53 UTC

The Problem: Runtime Memory Corruption
An EAccessViolation occurs when a VCL application attempts to read from or write to a memory address that it does not own or that no longer contains a valid object. This typically manifests as an abrupt application crash with the error message "Access violation at address..."
The core issue is almost always a pointer mismatch: the code is attempting to call a method or access a property of an object that is either nil (not yet created) or a "dangling pointer" (already freed, but the variable still holds the old memory address).
Diagnostic Matrix
| Symptom | Likely Cause | Diagnostic Indicator |
|---|---|---|
| Crash occurs immediately upon accessing a property | Nil Pointer | Debugger shows object instance as $0 or nil |
| Crash occurs randomly or after a specific object is closed | Dangling Pointer | Debugger shows a non-zero address, but the object type is invalid |
| Crash occurs during form destruction or application exit | Invalid Destruction Order | Call stack shows TCustomForm.Destroy or Finalize |
| Crash occurs inside a third-party component | External Memory Corruption | Call stack terminates in a .bpl or .dll without source |
Step-by-Step Investigation
1. Configure the Debugging Environment
Before attempting to reproduce the crash, ensure the IDE can provide an accurate call stack. Without these settings, the debugger may point to the wrong line of code.
- Navigate to Project > Options > Delphi Compiler > Compiling.
- Enable Debug DC and Full Debug Symbols.
- Ensure Optimization is turned off to prevent the compiler from rearranging code, which can obscure the exact crash site.
2. Isolate the Fault Line
Run the application via the IDE (F9). When the EAccessViolation triggers, the IDE will pause execution and highlight the offending line.
Check the Call Stack: Go to View > Debug Windows > Call Stack. This allows you to see the chain of events leading to the crash. If the crash is in a generic VCL method, look further down the stack to find the last line of your own code that was executed.
3. Inspect the Object State
Hover over the object instance causing the error. If the value is nil, the object was never instantiated. If the value is a hexadecimal address but the properties appear as garbage data, the object has been freed but the pointer was not cleared.
Implementing the Fix
Scenario A: The Nil Pointer
If the object is nil, wrap the access in an Assigned() check. This is critical for objects created dynamically at runtime.
// Risk: Accessing a property of a potentially uninitialized object
if Assigned(MyCustomObject) then
begin
MyCustomObject.PerformAction;
end
else
begin
// Handle the missing object (e.g., log error or instantiate)
end;
Scenario B: The Dangling Pointer
If the object was already freed, using .Free is insufficient because it leaves the variable holding the old address. Use FreeAndNil() to ensure the pointer is cleared immediately after the memory is released.
// Run this in the context of the object's owner or the managing class
// Required Permissions: Access to the object instance variable
FreeAndNil(MyCustomObject);
Verification: After implementing FreeAndNil, any subsequent Assigned() checks will correctly return False, preventing the access violation.
Scenario C: The Destruction Sequence
If the crash occurs during application shutdown, check if a background thread or a timer is attempting to access a form that has already been destroyed. Move the cleanup logic to the OnDestroy event of the owner form to ensure dependencies are released in the correct order.
Limitations and Risks
- Performance: While
FreeAndNilis safer, calling it thousands of times per second in a tight loop may introduce a negligible performance hit compared to a rawFree. - False Positives: Memory corruption can happen in one part of the app but only trigger a crash much later. If the debugger points to a line that seems logically impossible to fail, the memory may have been corrupted elsewhere.
Escalation Criteria
If the following conditions are met, the issue is likely outside the scope of standard VCL pointer management:
- The call stack ends inside a third-party
.bplor.dll. - The crash address changes every time the application runs despite identical input.
- The violation occurs within the
TMemoryManageritself.
In these cases, integrate FastMM4 (Full Debug Mode) to track memory leaks and invalid pointer writes in real-time, or contact the third-party vendor with the captured call stack.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.