Muzaffer
Muzaffer

Reputation: 5

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.

Upvotes: 0

Views: 138

Answers (3)

Gerhardh
Gerhardh

Reputation: 12404

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.

Upvotes: 0

KamilCuk
KamilCuk

Reputation: 141698

When dealing with void*, do arithmetic on char* or unsigned char* pointers.

void *allocated_mem_pointer = (char*)data + sizeof(size_t);

Upvotes: 0

Robert
Robert

Reputation: 2812

When you use pointers arithmetic (ie add a number to pointer) you need to type your pointer properly:

IntPointer32Bits + 1 => will give the address of the next adjacent 32 bits integer
IntPointer16Bits + 1 => will give the address of the next adjacent 16 bits integer

The resulting address of pointer arithmetic depends on the pointer type.

void* allocated_mem_pointer = data + sizeof(size_t);

In this case, data is a void *, so the pointer arithmetic is not clear for the compiler (need to calculate next 8 bits, next 16 bits or next 32 bits ?). You shouldn't use void * but you should have a real type instead, I assume uint8_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;

uint8_t *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
  uint8_t *allocated_mem_pointer = data + sizeof(size_t);

In this case, your intent is very clear for the compiler: the allocated_mem_pointer is a memory area composed of uint8_t, the computed address is the base address of data with an offset of size_t bytes. (the operator sizeof returns the number of bytes aka uint8_t.)

Upvotes: 0

Related Questions