module
Lapis::Docs::E_MEMORY_SAFETY_AND_ENGINE_INTERNALS::B_DEAD_POINTER_PROTECTION
Overview
Dead-Pointer Protection & Access Violation Defense
Comprehensive guide to Lapis's active dead-pointer protection mechanism, preventing
segmentation faults (ACCESS_VIOLATION / 0xC0000005) when nodes are freed by GDScript or the engine.
Executive Summary & Key Topics
| Topic | Method / Anchor | Description |
|---|---|---|
| Dead-Pointer Defense Primitives | .topic_00_defense_primitives |
Methods available on every Godot::Object wrapper for defensive lifetime inspection. |
| The Dead-Pointer Hazard | .topic_01_the_segfault_problem |
How standard bindings crash without stack traces and how Lapis defends against it. |
| Defensive Coding Patterns | .topic_02_defensive_coding_patterns |
Checking #alive? when holding references to transient entities. |
Related Guides & Source References
- Object Implementation:
src/libgodot/object.cr - Live Specs:
spec/suites/test_safety.cr
Defined in:
libgodot/docs/e_memory_safety_and_engine_internals/b_dead_pointer_protection.crClass Method Summary
-
.topic_00_defense_primitives : Nil
Dead-Pointer Defense Primitives: Methods available on every Godot::Object wrapper for defensive lifetime inspection.
-
.topic_01_the_segfault_problem : Nil
The Dead-Pointer Hazard: How standard bindings crash without stack traces and how Lapis defends against it.
-
.topic_02_defensive_coding_patterns : Nil
Defensive Coding Patterns: Checking #alive? when holding references to transient entities.
Class Method Detail
Dead-Pointer Defense Primitives: Methods available on every Godot::Object wrapper for defensive lifetime inspection.
Key Topics & Information
- object.alive? : Returns true if native C++ engine object is still valid
- object.destroyed? : Returns true if node was freed in GDScript or Godot
- object.check_alive! : Raises Godot::DisposedObjectError if freed
The Dead-Pointer Hazard: How standard bindings crash without stack traces and how Lapis defends against it.
If an entity (e.g. an enemy) is deleted in GDScript via queue_free(), standard C bindings retain a dangling raw pointer. Dereferencing this pointer triggers an immediate unrecoverable crash:
ACCESS_VIOLATION (0xC0000005)
In Lapis, every virtual dispatch and reflection call invokes #check_alive!:
def check_alive! : Void
return if @pointer.null?
unless Bridge.is_instance_id_valid(@instance_id)
@pointer = Pointer(Void).null
raise Godot::DisposedObjectError.new("Cannot access disposed Godot object")
end
end
Instead of crashing the game, you get a clean, catchable Crystal exception with full stack trace!
Defensive Coding Patterns: Checking #alive? when holding references to transient entities.
node Tower < Node2D do
@target : Enemy? = nil
def _physics_process(delta : Float64) : Void
# Check alive before firing:
if enemy = @target
if enemy.alive?
fire_at(enemy.global_position)
else
@target = nil # Clear stale reference
end
end
end
end