Home > OS >  Using realloc to reduce the size of a memory block
Using realloc to reduce the size of a memory block

Time:11-11

A little more than 20 years ago I had some grasp of writing something small in C , but even at that time, I probably didn't really do things right all the time. Now I'm trying to learn C again, so I'm really a newbie.

Based on this article: Using realloc to shrink the allocated memory , I made this test, which works, but troubles me:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int test (char *param) {
    char *s = malloc(strlen(param));
    strcpy(s, param);
    printf("original string    : [M] %s \n",  strlen(s), s);
    // reduce size
    char *tmp = realloc(s, 5);
    if (tmp == NULL) {
        printf("Failed\n");
        free(s);
        exit(1);
    } else {
        tmp[4] = 0;
    }
    s = tmp;
    printf("the reduced string : [M] %s\n", strlen(s), s );
    free(s);
}

void main(void){
    test("This is a string with a certain length!");
}
  1. If I leave out "tmp[4] = 0", then I still get back the whole string. Does this mean the rest of the string is still in memory, but not allocated anymore?
  2. how does c free memory anyway? Does it keep track of memory by itself or is it something that is handled by the OS?
  3. I free the s string "free(s)", do I also need to free the tmp str (it does point to the same memory block, yet the (same) address it holds is probably stored on another memory location?

These are most likely just basics, but none of what I have read so far has given me a clear answer (including mentioned article).

CodePudding user response:

  1. If I leave out "tmp[4] = 0", then I still get back the whole string.

You've invoked undefined behavior. All the string operations require the argument to be a null-terminated array of characters. If you reduce the size of the allocation so it doesn't include the null terminator, you're accessing outside the allocation when it tries to find it.

Does this mean the rest of the string is still in memory, but not allocated anymore?

In practice, many implementations don't actually re-allocate anything when you shrink the size. They simply update the bookkeeping information to say that the allocated length is shorter, and return the original pointer. So the remainder of the string stays the same unless you do another allocation that happens to use that memory.

This can even happen when you grow the size. Some designs always allocate memory in specific granularities (e.g. powers of 2), so if you grow the allocation but it doesn't exceed the granularity, it doesn't need to copy the data.

  1. how does c free memory anyway? Does it keep track of memory by itself or is it something that is handled by the OS?

Heap management is part of the C runtime library. It can use a variety of strategies.

  1. I free the s string "free(s)", do I also need to free the tmp str (it does point to the same memory block, yet the (same) address it holds is probably stored on another memory location?

After s = tmp;, both s and tmp point to the same allocated memory block. You only need to free one of them.

BTW, the initial allocation should be:

char *s = malloc(strlen(param) 1);

You need to add 1 for the null terminator, since strlen() doesn't count this.

  •  Tags:  
  • c
  • Related