I wonder what you are trying to achieve. If your process is deterministic, then the distribution / release scheme should be the same.
The only possible difference could be the address returned by malloc
. But you probably shouldn't depend on them (the easiest way is to not use pointers as a key map or other data structure). And even in this case, the difference should only be if the distribution is not performed via sbrk
(glibc uses anonymous mmap
for large allocations) or if you use mmap
(since the address is selected by the kernel by default).
If you really want to have exactly the same address, one option is to have a large static buffer and write your own allocator that uses the memory from this buffer. This has a drawback that makes you know in advance the maximum amount of memory you will ever need. In the non-PIE executable ( gcc -fno-pie -no-pie
), the static buffer will always have the same address. For the PIE executable, you can disable the randomization of the kernel address space structure for loading programs. In a shared library, disabling ASLR and running the same program twice should cause the dynamic linker to make the same choice of library display location.
If you do not know in advance what maximum memory size you want to use, or if you do not want to recompile this increase in size each time, you can also use mmap
to map a large anonymous buffer to a fixed address. Just pass the buffer size and address to use as a parameter to your process and use the returned memory to implement your own malloc
on top of it.
static void* malloc_buffer = NULL; static size_t malloc_buffer_len = 0; void* malloc(size_t size) {
Using MAP_FIXED
, we tell the kernel to replace any existing mappings that overlap with this new one in buf_addr
.
(Editor's note: MAP_FIXED
is probably not what you need . Specifying buf_addr
as a hint instead of NULL
already asks for this address, if possible. With MAP_FIXED
mmap
either return an error or the address you gave it. malloc_buffer != (void*)but_addr
checking malloc_buffer != (void*)but_addr
makes sense for the non- FIXED
case, which does not replace the existing display of your code, shared library or anything else. In Linux 4.17, MAP_FIXED_NOREPLACE
appeared MAP_FIXED_NOREPLACE
which can be used so mmap returns an error instead of memory to the wrong address that you donโt want to use. But nevertheless, leave the checkbox selected so that your code runs on older kernels.)
If you use this block to implement your own malloc and do not use other non- deterministic operations in your code, you can completely control the pointer values.
This assumes that your use of the malloc / free pattern is deterministic. And that you do not use libraries that are non-deterministic.
However, I think a simpler solution is to keep your algorithms deterministic and not depend on addresses. It is possible. I worked on a large-scale project in which several computers had to determine the state in detail (so that each program had the same state, transmitting only the input data). If you do not use the pointer for anything other than a reference to objects (the most important thing is never to use the value of the pointer for anything other than a hash code, not as a key on the map, ...), then your state will remain deterministic ,
If you need to take a snapshot of the entire process memory and perform a binary analysis to determine the discrepancy. I think this is a bad idea, because how do you know that both of them have reached the same point in their calculations? It is much easier to compare the output, or so that the process can calculate the status hash and use it to check if it is synchronized, because you can control when it will be done (and thus it will become deterministic, otherwise your measurement will be non- deterministic )