C realloc not changing array

228 views Asked by At

So, to start off I've already looked at a few questions including this one and none of them seem to help.

I'm simply trying to write a function that extends the size of an array using realloc().

My code currently looks like this:

unsigned char *xtnd = malloc(4);
xtndc(&xtnd, 4);
// sizeof(*xtnd) should now be 8

void xtndc ( unsigned char ** bytesRef , uint8_t count ) {
    *bytesRef = realloc(*bytesRef, (sizeof(**bytesRef)) + count);
}

But no matter what I do it seems that the size of xtnd is always 4. After running xtndc() on it it should now be 8 bytes long.

Any suggestions?

4

There are 4 answers

0
sth On BEST ANSWER

The type of **bytesRef is unsigned char, so sizeof(**bytesRef) is 1. sizeof doesn't keep track of dynamic allocations, it's a compile time tool that gives you the size of a type, in this case unsigned char.

You have to keep track of the array size manually to calculate the new required size.

0
VHS On

Your program does in fact change the size of the memory block. It changes the size of your original memory block from 4 bytes to 5 bytes. It changes to 5 bytes because you are essentially doing sizeof(unsigned char) + 4 which 1 + 4 = 5. If you want to double the size instead, do count*sizeof(unsigned char) + count. There are two points to be noted here:

  1. The sizeof function returns the size of the data type, not the size of the allocated bytes. There is no way to know the size of the dynamically allocated memory.
  2. The function realloc (and malloc and calloc as well) is not always guaranteed to return the requested reallocation. It may or may not succeed all the time.
3
Nathan F. On

I fixed the problem with the following code.

typedef struct CArrPtr {
    unsigned char* ptr;
    size_t size;
} CArrPtr;
void xtndc ( CArrPtr *bytesRef, uint8_t count );

. . .    

CArrPtr xtnd = { .ptr = malloc(4), .size = 4 };
xtndc( &xtnd, 4 );
// xtnd.size is now 8 bytes 

. . . 

void xtndc ( CArrPtr *bytesRef, uint8_t count ) {
    unsigned char *nptr;
    if((nptr = realloc(bytesRef->ptr, bytesRef->size + count)) != 0) 
    {
        bytesRef->ptr = nptr;
        bytesRef->size = bytesRef->size + count;
    }
}

As I am somewhat new to C, what I learned from this is that malloc specifically creates a pointer to a memory block, but you have no direct access to information about the memory block. Instead, you must store the size of the array that you created with malloc somewhere as well.

Since in the past I'd been initializing arrays with unsigned char arr[size]; and then using sizeof on it, I was under the impression that sizeof returned the size of the array, which is of course wrong as it gives you the size of a type.

Glad I could learn something from this.

0
smilingwang On
  1. sizeof is used to calculate size of data type or array. Pointer and array are very similar, but they are different things. For int *ap, sizeof(ap) will return 4 on x86, sizeof(*ap) will return 4; for int a[10], sizeof(a) will return 40.

  2. sizeof expression is processed at compile time, so it will be a constant written into the executable file before you run the program.

  3. malloc and realloc don't maintain size.

  4. If realloc succeeds, it will reallocate the requested size. So you don't need to check the size after realloc returns, but you should check the return value of realloc to ensure that realloc succeeds.