-7

I want to change malloc() function to calloc(), but I am confused: how I can do it in this piece of code?

void *mymalloc(size_t len)
{

    void *buf;
    size_t pages = (len & PAGE_MASK) + 2;
    size_t offset = PAGE_SIZE - (len & ~PAGE_MASK);

    if(offset < sizeof(size_t))
    {
        pages++;
        offset += PAGE_SIZE;
    }

    if((buf = mmap(NULL, pages << PAGE_SHIFT, PROT_READ | PROT_WRITE, 
                    MAP_PRIVATE | MAP_ANONYMOUS, 0, 0)) == -1)
    {
        perror("mymalloc/mmap");
        exit(1);
    }
    *(size_t *)buf = len;
    *(size_t *)(buf+offset+len) = len;

    if(mprotect(buf+offset+len, PAGE_SIZE, PROT_NONE) == -1)
    {
        perror("mymalloc/mprotect");
        exit(1);
    }

    return buf+offset;
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
rubi.r
  • 1
  • 1
    There is no `malloc()` in your code now. What are you asking? – wallyk Jan 29 '16 at 20:47
  • There is no `malloc()` there; there's just a `mymalloc()`. Presumably, you want a `mycalloc()` that calls `mymalloc()` and then zeroes the space. You also have to account for `malloc()` taking one argument and `calloc()` taking two that have to be multiplied to produce the requested size. – Jonathan Leffler Jan 29 '16 at 20:47
  • http://pubs.opengroup.org/onlinepubs/009695399/functions/mmap.html the very FIRST google result – RisingSun Jan 29 '16 at 20:48

2 Answers2

2

calloc() is effectively just malloc() with a memset() to zero.

Assuming you want a mycalloc() to supplement your mymalloc():

void *mymalloc( size_t bytes )
{
    ...
    return( ptr );
}

you'd get:

void *mycalloc( size_t bytes, size_t n )
{
    size_t total_bytes = bytes * n;
    void *ptr = mymalloc( total_bytes );
    memset( ptr, 0, total_bytes );
    return( ptr );
}

You'll want to add checks for multiplication overflow and NULL returns from mymalloc().

Andrew Henle
  • 32,625
  • 3
  • 24
  • 56
  • 1
    You are forgetting to make sure that the multiplication does not overflow. – Deduplicator Jan 29 '16 at 20:52
  • @Deduplicator I want to leave *something* for the OP to figure out... [And no, I wasn't forgetting. ;-)] – Andrew Henle Jan 29 '16 at 20:52
  • 2
    If your target environment is Linux, you don't even need the memset, MAP_ANONYMOUS pages come zerod. – John Hascall Jan 29 '16 at 20:56
  • @JohnHascall True. That does make the `mycalloc()` implementation dependent upon `mymalloc()` returning zeroed memory though. – Andrew Henle Jan 29 '16 at 21:04
  • 1
    Yes, my comment was mostly an aside. if you really wanted to do this you would best surround the `memset` with a feature test macro, something like `#ifndef _HAVE_ZEROING_ANON_MMAP` – John Hascall Jan 29 '16 at 21:07
0

When you have questions like this, always check manual pages:

  • Malloc:

void *malloc(size_t size); The malloc() function allocates size bytes and returns a pointer to the allocated memory. The memory is not initialized. If size is 0, then malloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

  • Calloc:

void *calloc(size_t nmemb, size_t size); The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. The memory is set to zero. If nmemb or size is 0, then calloc() returns either NULL, or a unique pointer value that can later be successfully passed to free().

Difference is that calloc also initialize allocated block of memory to zeroes.

Aleksandar Makragić
  • 1,957
  • 17
  • 32
  • Note: A second difference, not seen much today, is that `calloc()` could handle allocations like `calloc(SIZE_MAX/8, 16)` whereas `malloc()` cannot. Useful on segmented architectures. – chux - Reinstate Monica Jan 29 '16 at 22:01