Difference between revisions of "Lua:getAddressSafe"

From Cheat Engine
Jump to navigation Jump to search
(added more detailed documentation as well as examples and comparison with getAddress)
m (Added related function template.)
 
(2 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
[[Category:Lua]]
 
[[Category:Lua]]
'''function''' getAddressSafe(''AddressString'', ''local'' OPTIONAL, ''shallow'' OPTIONAL) ''':''' integer
+
{{CodeBox|'''function''' getAddressSafe(''symbolname'', ''local'', ''shallow'') ''':''' integer}}
  
Safely resolves a symbol name to a memory address without raising exceptions. Returns nil on failure instead of throwing an error.
+
Returns the address of a symbol, or nil if the symbol could not be resolved.
  
'''Note:''' This is the recommended function for symbol resolution when the symbol might not exist.
+
This function is similar to using getAddress with errorOnLookup set to false, but returns nil instead of raising an error when the symbol is not found.
  
=== Function Parameters ===
+
The symbol can be a registered symbol, a module name, or an exported symbol. Set ''local'' to true to query the symbol table of the Cheat Engine process instead of the currently opened target process.
  
{|width="85%" cellpadding="10%" cellpadding="5%" cellspacing="0" border="0"
+
===Function Parameters===
 +
{|width="85%" cellpadding="10%" cellspacing="0" border="0"
 
!align="left"|Parameter
 
!align="left"|Parameter
 
!align="left"|Type
 
!align="left"|Type
!style="width: 80%;" align="left"|Description
+
!style="width: 80%;background-color:white;" align="left"|Description
 
|-
 
|-
|AddressString
+
|symbolname
|string or number ('''[[CEAddressString]]''')
+
|String
|The symbol to resolve (module name, address expression, label, pointer expression). If a '''number''' is provided, it's returned unchanged
+
|The symbol, module name, or exported symbol to resolve.
 
|-
 
|-
 
|local
 
|local
|boolean
+
|Boolean (optional)
|'''Optional.''' If true, uses Cheat Engine's self symbol handler instead of the target process. Default: '''false'''
+
|If true, queries the symbol table of the Cheat Engine process.
 
|-
 
|-
 
|shallow
 
|shallow
|boolean
+
|Boolean (optional)
|'''Optional.''' If true, performs a shallow (faster) symbol lookup without deep parsing. Default: '''false'''
+
|If true, performs a shallow lookup.
 
|}
 
|}
  
 +
===Returns===
 +
integer or nil — The resolved address of the given symbol, or nil if the symbol could not be found.
  
=== Returns ===
+
===Examples===
An integer representing the resolved address on success, or '''nil''' if resolution fails.
+
<syntaxhighlight lang="lua" line>
 
+
local address = getAddressSafe("KERNEL32.AddAtomA")
=== Description ===
 
 
 
This function works identically to [[Lua:getAddress|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 ===
 
 
 
* '''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 ===
 
 
 
'''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 ===
 
 
 
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 ===
 
 
 
{|width="85%" cellpadding="10%" cellpadding="5%" cellspacing="0" border="1"
 
!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 ===
 
 
 
'''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 ===
 
 
 
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 ===
 
 
 
* 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 ===
 
 
 
'''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")
 
  
 +
if address ~= nil then
 +
  print(string.format("%X", address))
 +
else
 +
  print("Symbol could not be resolved")
 +
end
 +
</syntaxhighlight>
  
 
{{LuaSeeAlso}}
 
{{LuaSeeAlso}}
  
=== Related Functions ===
+
{{Address}}
* [[Lua:getAddress|getAddress]]
 
* [[Lua:getNameFromAddress|getNameFromAddress]]
 
* [[Lua:getCommonModuleList|getCommonModuleList]]
 
* [[Lua:inModule|inModule]]
 
* [[Lua:inSystemModule|inSystemModule]]
 
* [[Lua:targetIs64Bit|targetIs64Bit]]
 
* [[Lua:enumModules|enumModules]]
 
* [[Lua:registerSymbol|registerSymbol]]
 
* [[Lua:unregisterSymbol|unregisterSymbol]]
 
* [[Lua:AOBScanUnique|AOBScanUnique]]
 

Latest revision as of 22:48, 26 June 2026

<> Lua API Reference

function getAddressSafe(symbolname, local, shallow) : integer

Returns the address of a symbol, or nil if the symbol could not be resolved.

This function is similar to using getAddress with errorOnLookup set to false, but returns nil instead of raising an error when the symbol is not found.

The symbol can be a registered symbol, a module name, or an exported symbol. Set local to true to query the symbol table of the Cheat Engine process instead of the currently opened target process.

Function Parameters[edit]

Parameter Type Description
symbolname String The symbol, module name, or exported symbol to resolve.
local Boolean (optional) If true, queries the symbol table of the Cheat Engine process.
shallow Boolean (optional) If true, performs a shallow lookup.

Returns[edit]

integer or nil — The resolved address of the given symbol, or nil if the symbol could not be found.

Examples[edit]

1 local address = getAddressSafe("KERNEL32.AddAtomA")
2 
3 if address ~= nil then
4   print(string.format("%X", address))
5 else
6   print("Symbol could not be resolved")
7 end

Main Pages

Core Lua documentation entry points

Lua
Script Engine

Symbol Related Lua Functions

Symbol lookup, address resolution, module checks, and lookup callbacks