0

When I run the below code, I get the given output.

#include <stdio.h> /* printf */
#include <stdlib.h> /* malloc, realloc */

int main()
{
    char* characters = (char *) malloc(10 * sizeof(char));
    printf("Before: characters at %p, size=%lu\n", (void *) characters, sizeof(characters) / sizeof(characters[0]));
    char* temp = (char *) realloc(characters, 100);
    if (temp)
    {
        printf("After realloc, characters size = %lu, temp size = %lu\n", sizeof(characters) / sizeof(characters[0]), sizeof(temp) / sizeof(temp[0]));
        printf("After realloc, nums at %p, temp at %p\n", (void *) characters, (void *) temp);
        //characters = temp;
        free(temp);
    }
    free(characters);
}

/* Output:
Before: characters at 0x107b00900, size=8
After realloc, characters size = 8, temp size = 8
After realloc, nums at 0x107b00900, temp at 0x107b00910
test(3556) malloc: *** error for object 0x107b00900: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
*/

I'm trying to figure out what is malfunctioning. I think that malloc sets aside space for ten consecutive characters and gives me a pointer to the first element of that array, and I store that pointer in characters. I then print the size of characters, and I expect 10, but I get 8. That's the first weird thing. Then, I ask realloc to find a new spot in the heap, which has space for 100 consecutive characters and return to me a pointer to the first spot. I put that pointer into temp. When I print temp's size, I get 8 (again), even though I expect 100. When I print the pointers to characters and temp, I get two different locations in the heap. Usually, I would then reassign the characters pointer to point to whatever temp is pointing to. Then I tried to free my pointers, and it told me that it couldn't free 0x107b00900, the exact location characters is, because the object at that point wasn't malloced; however, I did malloc space for characters. Why is this happening? Am I misunderstanding the functionality of malloc, realloc, sizeof, or something else? Thank you for your help.

sredmond
  • 460
  • 3
  • 15

2 Answers2

3

You can't use sizeof on your pointer to get the amount of memory allocated.

char* characters = (char *) malloc(10 * sizeof(char));

The characters variable does not know how much space it is pointing to. It's your job to keep track of it.

As far as

char* temp = (char *) realloc(characters, 100);

realloc can move the memory block - which is what happens here. When it does that it marks the memory originally pointed to by characters as unallocated. Thus, when you free characters on the last line, you get an error because you are freeing memory that the system has marked as unallocated.

001
  • 13,291
  • 5
  • 35
  • 66
  • Yes you can, but the size of the pointer (4 on a 32 bit system) is not what is needed by the OP. – Jabberwocky Mar 06 '14 at 16:36
  • True. It seems like I can't possibly get the length of the space that the char* has been allocated. The closest I could get would be `strlen`, but that only gives the length of any null-terminated string in the consecutive sequence of characters – sredmond Mar 06 '14 at 16:40
3

There is no way to find the actual size allocated by alloc/realloc. The trick with dividing the size of characters by size of *characters works only for arrays; it does not work for pointers.

The library does not keep track of the size of the allocated chunk of memory in a way that would be available to the users of the standard library. It may store some information for its own use, but there is no user-facing call to retrieve it.

A common way of working around this issue is to store the size of the allocation along with the pointer to the allocated area.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • I usually store (number of items) and (pointer to items) whenever I use realloc, not the size of the allocation. Looks more readable to me. And if you don't want to reallocate all the time, you often allocate a bit more than is needed right now, so you don't need to realloc if you need one more item. In that case, you have a triple (how many allocated items, how many items in use, pointer to allocated items). – gnasher729 Mar 06 '14 at 17:08