Search code examples
pointerscrystal-lang

Are crystal heap pointers always even?


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)?


Solution

  • 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.