Search code examples
cmemorymallocmmap

using pointer aritmetic in void*


My machine is ubuntu 20.04

I have a assignment that say "Using the system calls (mmap and munmap) implement your own functions for dynamic memory allocation: mymalloc and myfree, which have the same functionality as malloc and free from the standard C library. Save the implementations in files mymalloc.h and mymalloc.c."

And then it says "we must allocate at least the desired length + the size of the variable for storing the length (size_t). We store the length as first element, then return the next element."

It is my code (size is parameter in type size_t)

size_t total_size = size + sizeof(size_t);

size_t allocation_overflow = total_size % page_size;

if(allocation_overflow > 0)
    total_size += page_size - allocation_overflow;

void *data = mmap(NULL ,total_size, PROT_EXEC | PROT_READ | PROT_WRITE , MAP_PRIVATE , 0 , 0);

  // size_ptr will point to stored size
  size_t *size_ptr =(size_t *)data;

  size_ptr[0] = total_size;


  // pointer to allocated memory
  void* allocated_mem_pointer = data + sizeof(size_t);

and it give warning "pointer type 'void*' used in arithmetic [-Wpointer arith]"

ı must store the length in first element because assignment says it but ı don't warnings ı want to write clean code . İS there a legal for it. I already read Pointer arithmetic when void has unknown size but couldnt find any answer to solve it.


Solution

  • As you found out, you cannot do arithmetics with void* unless you are using GCC extensions or similar.

    The simple solution is: Don't use void*.

    In your code you already have

      // size_ptr will point to stored size
      size_t *size_ptr =(size_t *)data;
      size_ptr[0] = total_size;
    

    Now you want to calculate the address that comes after your counter header.

    The element that comes after arr[0] is simply arr[1].

    Use this to get the address for caller:

      // pointer to allocated memory
      void* allocated_mem_pointer = &size_ptr[1];
    

    When you want to get back to that header in your myfree function you can do similar trick:

    void myfree(void*addr) {
       size_t *buff = (size_t*) addr;
       size_t header = buff[-1];
       // ... 
    }
    

    This is valid because buff[-1] points into the same memory oject that was initially allocated in your myalloc function.

    Note:

    If you were to create a function that is not only used for educational purposes, you would also need to handle proper alignment for the address you return to the caller.