I tried this code:
GC.disable
class A
end
a = [] of UInt64
10000000.times do
tmp = A.new.as(Void*).address
tmp %= 10
a << tmp if !a.includes? tmp
end
puts a.sort
And it returned me [0_u64, 2_u64, 4_u64, 6_u64, 8_u64]
, meaning all the pointer addresses are even.
Is it true heap pointer addresses are always even in Crystal? If it is, why (whether there is any explanation for this)?
Assuming all instances are allocated consecutively, each pointer has to be apart from the previous one (at least) by the size of memory that was allocated.
You can get the size of an instance of A
with instance_sizeof(A)
which in this case is 4
bytes. Therefore, ignoring any padding, all memory addresses are multiples of 4
and the last digit of each number in this series is even.
This is not the only reason, though.
If you allocate memory on the heap, the malloc
implementation needs to assign an address of free memory and maybe even stores some internal data about that memory allocation. This implementation typically follows some rules for assigning addresses.
For example, in glibc, all memory addresses allocated by malloc
are multiples of 8
(32-bit) or 16
(64-bit) (see http://www.delorie.com/gnu/docs/glibc/libc_31.html).
This is of course system specific, and other implementations might have different rules.
So in your example, assuming it is used with glibc, even if A
had an instance size of 10
, addresses would still be multiples of 8
or 16
.