What you're doing is touching on Undefined Behavior, and is Ill Advised at the very least. If you need fine-grained control over memory blocks like this, you need to ask the system's memory allocator to give you a large block to manage yourself.
The system allocator is shared between your threads and any system or other allocating calls you make - such as strdup. The reordering that happens with realloc is caused by the fact that realloc must first allocate a new block and then copy the old data into it before making the older block available. But this same problem is going to occur elsewhere in your application's lifetime.
There are also many memory-allocator strategies. Some memory allocators will actually allocate a slightly larger block than you request and use the extra space to provide information about the allocation. E.g. when you ask for 16 bytes of memory, they allocate 16 + sizeof(size_t) and store the size of the allocation infront of the address they return to you:
void* malloc(size_t bytes)
{
uint32_t* block = _internal_malloc(bytes + sizeof uint32_t);
*block = bytes;
return &block[1]; // return a pointer to after the size we stored.
}
Memory allocators also tend to change between versions of operating systems, so relying on their behavior is a pretty bad idea.
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int main() {
char* a = malloc(32);
char* b = malloc(32);
char* s = strdup("hello");
char* c = malloc(32);
printf("a = %p, b = %p (a + 32 = %p), c = %p (b + 32 = %p)\n", a, b, a+32, c, b + 32);
// your code goes here
return 0;
}
Output:
a = 0x83af008, b = 0x83af030 (a + 32 = 0x83af028), c = 0x83af068 (b + 32 = 0x83af050)
You can see that these blocks are in order but not contiguous, there's also an extended gap between b and c because of the strdup.
Another issue that can affect ordering is fragmentation of the free pool.
http://ideone.com/cbAfzm
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
int main() {
char* a = malloc(32);
char* b = malloc(32);
char* s = strdup("hello");
free(s);
char* c = malloc(32);
printf("a = %p, b = %p (a + 32 = %p), c = %p (b + 32 = %p)\n", a, b, a+32, c, b + 32);
// your code goes here
return 0;
}
Here, even though we free
d s, we've fragmented the allocation causing a split and we're only going to get that address back when we ask for an equal or smaller allocation.