tags:

views:

438

answers:

3

What I decided to do is

  • call malloc
  • copy the old block to the new block
  • free the old block
  • and return the pointer to the new block

The code below is what I have so far...but I know it is not right...any help on fixing the code would be greatly appreciated...

If you need more code than what I have provided I have a post previous to this one which shows all the code. I'm new so there is only this post and the last post I have done. Thank You.

void *mm_realloc(void *ptr, size_t size)
{
int i, p = *ptr;

 // make a call to malloc to find space
 //allocate memory

 ptr = malloc(size_t*sizeof(int));

 //copying old block to new block
 if(ptr!=NULL)
     for(i=0 ; i<size_t ; i++) 
     {
     *(ptr+i) = i;
     }

//freeing old block
free(ptr);

//return pointer to new block
return *ptr;
}
+1  A: 

You need to know how big the old block is as well as the new size. You have to copy the lesser of the two sizes over the new block.

You also have to ensure that you do not destroy (free) the old block if the malloc() fails - you just return 0.

You also don't need to multiply the size by 'sizeof(int)' in the malloc(); you are really overallocating by a factor of 4 or more (in theory, it might be only a factor of 2, but few people use 16-bit compilers these days).

Jonathan Leffler
And some of us, working on big iron boxes (and even some puny little Linux and Windows boxes nowadays), have 64-bit integers :-)
paxdiablo
Indeed - and MacOS X too. That possibility is covered by the 'or more', of course.
Jonathan Leffler
There are machines where `sizeof(int) == 8`? Do you simply do without 2 or 4 byte integers?
Simon Buchan
You look to see whether either or both of uint16_t and uint32_t are defined in (C99) header `<stdint.h>` (they are a typedef, but the corresponding limits are #defines).
Jonathan Leffler
+1  A: 

The point of realloc is that it tries to merge the block of memory with a free one behind that, if possible. Only if there isn't a free one, will it allocate new memory, copy everything over, and frees the old block.

Why are you writing your own allocation routines anyway?

sbi
@sbi: training exercise
Jonathan Leffler
training exercise.
jingojango
+1  A: 

Ideally, a realloc() would simply see if there's enough free memory beyond the current block and, if so, just adjust the arena data structures to expand the current block in-place. This gets rid of the expensive copy operation and reduces the chances of allocation failure. That's for increasing the size. For reducing, you should be able to do it in-place always, sending the remainder of the current block back to the free pool.

By doing a malloc/free, if you have 100K in the arena with a single 60K block allocated, calling your mm_realloc to adjust the size to 50K will fail.

However, it is a workable solution, at least for a first attempt, so here's how I'd implement it:

void *mm_realloc (void *ptr, size_t size) {
    int minsize;
    void *newptr;

    // Allocate new block, returning NULL if not possible.

    newptr = malloc (size);
    if (newptr == NULL) return NULL;

    // Don't copy/free original block if it was NULL.

    if (ptr != NULL) {
        // Get size to copy - mm_getsize must give you the size of the current block.
        // But, if new size is smaller, only copy that much. Many implementations
        // actually reserve the 16 bytes in front of the memory to store this info, e.g.,
        // +--------+--------------------------------+
        // | Header | Your data                      |
        // +--------+--------------------------------+
        //           ^
        //           +--- this is your pointer.
        // <- This is the memory actually allocated ->

        minsize = mm_getsize (ptr);
        if (size < minsize)
           minsize = size;

        // Copy the memory, free the old block and return the new block.

        memcpy (newptr, ptr, minsize);
        free (ptr)
    }

    return newptr;
}

One thing you'll notice that's missing from yours is that it has to copy only enough bytes for the smallest of the old and new blocks. Otherwise you risk core dumps by overflowing one of them.

In addition, your loop didn't actually copy the data, it set each byte of the block to its offset, and it lost the old pointer when allocating the new one, hence my use of newptr to keep them separate.

paxdiablo
Thank you ...This is more of what I was looking for...PLEASE anyone else who has any other code that would like to offer feel free to post it.
jingojango