The documentation says this about undefined
:
In Debug mode, Zig writes
0xaa
bytes to undefined memory. This is to catch bugs early, and to help detect use of undefined memory in a debugger. However, this behavior is only an implementation feature, not a language semantic, so it is not guaranteed to be observable to code.
I find myself wondering if this can (carefully) be promoted to a language semantic. Not this exact thing, but something like it.
Most of the time, we can do this:
threadlocal var some_ptr: *Pointer = undefined;
// Forgive the 'style violation'
const ILLEGAL_ADDRESS: usize = undefined;
// Ope!, did it again
fn debug_assert(ok: bool) void {
// Why is this still in caps btw?
if (builtin.mode == .Debug {
assert(ok);
}
}
// Later, in a function or something
debug_assert(@intFromPtr(some_ptr) != ILLEGAL_ADDRESS);
This will mostly work most of the time.
Problem is, Zig code canāt make the assumption that an illegal address exists, certainly not that itās 0xaaaa_aaaa
on 32 bit systems.
Something like this could work though:
const can_check = builtin.mode == .Debug and builtin.illegal_ptr_address != null;
const illegal_address: ?usize = builtin.illegal_ptr_address;
threadlocal var some_ptr: *Pointer = undefined;
fn ptr_ok(ptr: usize) void {
if (can_check)
assert(ptr != illegal_address.?);
}
// later
ptr_ok(@intFromPtr(some_ptr);
Basically: if there is an illegal pointer value, distinct from null
, then builtin.illegal_ptr_address
has that value, if not, itās null
. Then, in .Debug
mode (at least?) it will be correct to check a maybe-still-undefined
pointer integer value against builtin.illegal_ptr_address
. Otherwise all bets are off.
Most client code this will be true, thatās why that value of undefined
exists: the A Pointer is in kernel space, and you donāt get to look at it, so itās representative of a very large space of addresses which are illegal to reference.
Basically I would like to be able to write this check, such that it only compiles if it will always work.