Mabus Mabus - 2 months ago 5
C Question

What happened with the relocating allocator?

I was reading old glibc documentation here when I saw three strange functions that I had never seen before (r_alloc, r_alloc_free and r_re_alloc). They implemented an allocator that realocates memory for defragmentation purposes, I think, but I can't find more info anywhere else.

Can you tell me more about that functions? Are they still in Glibc? If not, why they were removed?


Can you tell me more about that functions?

What do you want to know about them? They are pretty clearly described in the manual in which you've found them.

They are somewhat similar to Win32 LocalAlloc and LocalLock -- you get a handle to memory object, but to get the usable address of that object requires an extra step. These are generally a bad idea, except on extremely memory constrained systems.

Are they still in Glibc?


If not, why they were removed?

Because they are generally a bad idea, and breed to hard-to-find bugs.


What kind of bugs are possible by using something like that?

Here is an example:

const char *my_strcat(const char *a, const char *b)
  const size_t len_a = strlen(a);
  const size_t len_b = strlen(b);
  void** handle = malloc(sizeof(void*));

  if (r_alloc((void**)handle, len_a + len_b + 1) == NULL) return NULL;
  memcpy(*handle, a, len_a);
  memcpy(*handle + len_a, b, len_b + 1);

  return handle;

// There are memory leaks here. Ignore them for now.
int main()
  void** block1 = my_strcat("def", "ghi");
  void** block2 = my_strcat("abc", (const char*)*block1);

  return strcmp((const char*)*block2, "abcdefghi");

Can you spot the bug?

The program will sometimes succeed, sometimes fail with non-zero exit code, and sometimes crash with SIGSEGV.

The reason is that after every call to r_* every handle can receive a new value; invalidating any pointers derived from them like the b parameter in the second call to my_strcat.