Lua:getAddressSafe
function getAddressSafe(AddressString, local OPTIONAL, shallow OPTIONAL) : integer
Safely resolves a symbol name to a memory address without raising exceptions. Returns nil on failure instead of throwing an error.
Note: This is the recommended function for symbol resolution when the symbol might not exist.
Contents
Function Parameters[edit]
| Parameter | Type | Description |
|---|---|---|
| AddressString | string or number (CEAddressString) | The symbol to resolve (module name, address expression, label, pointer expression). If a number is provided, it's returned unchanged |
| local | boolean | Optional. If true, uses Cheat Engine's self symbol handler instead of the target process. Default: false |
| shallow | boolean | Optional. If true, performs a shallow (faster) symbol lookup without deep parsing. Default: false |
Returns[edit]
An integer representing the resolved address on success, or nil if resolution fails.
Description[edit]
This function works identically to getAddress but returns nil on failure instead of raising an exception. It resolves:
- Module names (e.g., "game.exe", "kernel32.dll")
- Module + offset expressions (e.g., "game.exe+1234")
- Symbol names from debug symbols or exports
- Registered symbols from registerSymbol()
- Auto-assembler labels
- Pointer expressions
Return Behavior[edit]
- Success: Returns the resolved address as an integer
- Failure: Returns nil (nothing pushed to Lua stack)
- Numeric input: Returns the number unchanged
- Exceptions: Catches all exceptions and returns nil
Usage Examples[edit]
Basic safe resolution:
local address = getAddressSafe("game.exe+12345")
if address then
print(string.format("Address: %X", address))
else
print("Failed to resolve symbol")
end
Check if module exists:
local baseAddr = getAddressSafe("optionalModule.dll")
if baseAddr then
print("Module loaded at: " .. baseAddr)
else
print("Optional module not loaded")
end
Conditional feature detection:
local featureAddr = getAddressSafe("game.exe+NewFeatureOffset")
if featureAddr then
-- New version with feature
print("New version detected")
enableNewFeature(featureAddr)
else
-- Old version without feature
print("Old version, feature not available")
useOldMethod()
end
Safe symbol registration:
function tryRegisterSymbol(name, expr)
local addr = getAddressSafe(expr)
if addr then
registerSymbol(name, addr)
print(string.format("Registered %s = %X", name, addr))
return true
else
print("Warning: Failed to register " .. name)
return false
end
end
tryRegisterSymbol("PlayerHealth", "game.exe+ABCD")
Version-dependent code:
local v1Addr = getAddressSafe("game.exe+1000")
local v2Addr = getAddressSafe("game.exe+2000")
if v2Addr and readBytes(v2Addr) == 0x48 then
print("Using version 2 offsets")
healthAddr = v2Addr
elseif v1Addr then
print("Using version 1 offsets")
healthAddr = v1Addr
else
print("Unknown version!")
return false
end
Numeric pass-through:
local addr = getAddressSafe(0x12345678) -- Returns 0x12345678 unchanged print(addr) -- 305419896
With shallow lookup (faster):
-- Shallow lookup is faster but may miss complex expressions
local addr = getAddressSafe("game.exe", false, true)
if addr then
print("Quick module lookup: " .. addr)
end
Shallow vs Deep Lookup[edit]
The shallow parameter controls the symbol resolution depth:
Deep lookup (shallow = false, default):
- Performs full expression parsing
- Handles complex pointer arithmetic
- Resolves nested brackets and offsets
- Slower but more comprehensive
Shallow lookup (shallow = true):
- Quick module/symbol name lookup
- Skips complex expression evaluation
- Faster for simple module names
- May fail on complex expressions
Example:
-- Deep lookup (handles complex expressions)
local addr1 = getAddressSafe("[[game.exe+100]+8]+4", false, false)
-- Shallow lookup (fast, simple names only)
local addr2 = getAddressSafe("game.exe", false, true)
Comparison: getAddress vs getAddressSafe[edit]
| Feature | getAddress | getAddressSafe |
|---|---|---|
| On failure | Raises exception | Returns nil |
| Error handling | Requires pcall or try/catch | Simple if/then check |
| Use case | Symbol must exist | Symbol might not exist |
| Performance | Same | Slightly faster (no exception overhead on failure) |
| Code complexity | More complex (needs pcall) | Simpler (direct nil check) |
Advanced Examples[edit]
Multi-version support:
local offsets = {
v1 = "game.exe+10000",
v2 = "game.exe+20000",
v3 = "game.exe+30000"
}
local healthAddr = nil
for version, offset in pairs(offsets) do
local addr = getAddressSafe(offset)
if addr and readBytes(addr) == 0x89 then -- Signature check
healthAddr = addr
print("Detected " .. version)
break
end
end
if not healthAddr then
print("ERROR: No compatible version found!")
return false
end
Graceful degradation:
function findPlayerHealth()
-- Try primary location
local addr = getAddressSafe("PlayerHealthPrimary")
if addr then return addr end
-- Try secondary location
addr = getAddressSafe("game.exe+ABCD")
if addr then return addr end
-- Try pattern scan as fallback
addr = AOBScanUnique("89 44 24 ?? 8B 45", "+X")
if addr then
registerSymbol("PlayerHealthPrimary", addr)
return addr
end
return nil -- All methods failed
end
local health = findPlayerHealth()
if health then
print("Health found at: " .. health)
else
print("Could not locate health!")
end
Validate before use:
function safeWriteInteger(symbol, value)
local addr = getAddressSafe(symbol)
if not addr then
print("Error: Cannot resolve " .. symbol)
return false
end
writeInteger(addr, value)
return true
end
if safeWriteInteger("PlayerGold", 9999) then
print("Gold updated successfully")
end
Exception Safety[edit]
getAddressSafe catches ALL exceptions during symbol resolution:
-- These all return nil instead of crashing:
local addr1 = getAddressSafe("!@#$%^&*()") -- Invalid syntax
local addr2 = getAddressSafe(nil) -- Nil input
local addr3 = getAddressSafe("") -- Empty string
local addr4 = getAddressSafe("[[[[[") -- Malformed brackets
Performance Considerations[edit]
- Shallow lookups are faster for simple module names
- Deep lookups required for complex expressions
- Symbol resolution waits for symbol loading (can block)
- Cache resolved addresses in variables for repeated use:
-- Bad: Resolves every iteration
for i = 1, 1000 do
local addr = getAddressSafe("game.exe+1234")
writeInteger(addr, i)
end
-- Good: Resolve once, reuse
local addr = getAddressSafe("game.exe+1234")
if addr then
for i = 1, 1000 do
writeInteger(addr, i)
end
end
Common Patterns[edit]
Assert pattern (fail fast):
local addr = getAddressSafe("game.exe+1234")
assert(addr, "Failed to resolve game.exe+1234")
-- Continue with addr
Default value pattern:
local addr = getAddressSafe("game.exe+1234") or 0x400000
-- Use default if resolution fails
Chain pattern (try multiple):
local addr = getAddressSafe("NewSymbol") or
getAddressSafe("OldSymbol") or
getAddressSafe("game.exe+1234")
See also[edit]
| Lua |
| Script Engine |