0

In the lecture of week 4 in CS50x, David shows how to allocate memory using malloc() to clone a string, and how free() needs to be called whenever malloc() was called to free up allocated memory afterwards.

I can copy a string, change the copy and verify the source wasn't changed, but when I call free() on the copied variable, it removes all its contents.

This is the code:

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

// ---

int main(void)
{
    char *source = "profound words.";
    char *destination = malloc(strlen(source) + 1); // length of source plus 1 for \0 character
    if (destination == NULL)
    {
        return 1; // problem allocating memory
    }
    strcpy(destination, source);
    printf("before: source: %s, destination: %s\n", source, destination);
    printf("source memory: %p, destination memory: %p\n", &source, &destination);
    if (strlen(destination) > 0)
    {
        printf("uppercasing first letter of variable 'destination'\n");
        destination[0] = toupper(destination[0]);
    }
    // free(destination); // if executed, will scramble destination contents. why?
    printf("after: source: %s, destination: %s\n", source, destination);
    printf("source memory: %p, destination memory: %p\n", &source, &destination);
}

Outputs:

before: source: profound words., destination: profound words.

source memory: 0x7fff2514aef0, destination memory: 0x7fff2514aee8

uppercasing first letter of variable 'destination'

after: source: profound words., destination: Profound words.

source memory: 0x7fff2514aef0, destination memory: 0x7fff2514aee8

--> all good

However, when uncommenting the line free(destination);, the last output line would then be "after: source: profound words., destination: ".

Any ideas why that's happening?

1 Answer 1

1

It seems that maybe you haven't grasped the exact purpose of the free() function. Yes, it needs to be called at some point after a malloc call. BUT, not before the code is done using the memory.

When the free(destination) line is not commented out, it will release the memory that was allocated by the malloc call. When that happens, the pointer destination still contains the address of the memory, but the memory itself is released to be reused by the system. The contents of that memory address become totally unpredictable. It may not change, it may be reallocated to something else. There's no way to predict what will happen.

Having said that, you do need to execute the free(destination) call sometime before the end of the program as a best practice.

Try rewriting the last few lines like below to see a little more of how it works.

    }
    printf("after: source: %s, destination: %s\n", source, destination);
    printf("source memory: %p, destination memory: %p\n", &source, &destination);

    free(destination);

    printf("destination has been freed. \n");
    printf("after: source: %s, destination: %s\n", source, destination);
    printf("source memory: %p, destination memory: %p\n", &source, &destination);
}
1
  • Great, thanks a lot for the explanation. All clear now. Commented Jan 18, 2022 at 18:24

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .