1

Considering this simple program,

// preprocessor directives
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>

// define a struct
typedef struct structure
{
    string str;
}
structure;

// create a pointer
structure *ptr;

int main(void)
{
    // allocate memory for a structure
    ptr = malloc(sizeof(structure));

    if (ptr != NULL)
    {
        // prompt for a string
        printf("Give me a string: ");
        ptr -> str = GetString();
        free(ptr); // doesn't free the string
    }

    return 0;
}

When compiling and running it under valgrind, inputting "hi", it gives the following output:

==3573== HEAP SUMMARY:
==3573==     in use at exit: 3 bytes in 1 blocks
==3573==   total heap usage: 3 allocs, 2 frees, 43 bytes allocated
==3573== 
==3573== 3 bytes in 1 blocks are definitely lost in loss record 1 of 1
==3573==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==3573==    by 0x4E37D1A: GetString (in /usr/lib/libcs50.so)
==3573==    by 0x4007AD: main (structure.c:25)
==3573== 
==3573== LEAK SUMMARY:
==3573==    definitely lost: 3 bytes in 1 blocks
==3573==    indirectly lost: 0 bytes in 0 blocks
==3573==      possibly lost: 0 bytes in 0 blocks
==3573==    still reachable: 0 bytes in 0 blocks
==3573==         suppressed: 0 bytes in 0 blocks
==3573== 
==3573== For counts of detected and suppressed errors, rerun with: -v
==3573== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Which clearly states that there's a memory leak cause by a call to GetString().

The problem is that I already freed ptr which in turn contains a pointer to the same block of memory that contains the string created and returned by GetString(). However, I'm still having a memory leak unless I free ptr -> str manually. So what's going on here?

2

This question was also posed on Facebook by you here: https://www.facebook.com/groups/cs50/permalink/343562319124153/

In a nutshell, GetString() mallocs space to hold the character array that you then enter. Any "definitely lost" bytes that valgrind reports are from that GetString() malloc unless you specifically free it using free(s); or free(ptr->str); (because those both point to the same address).

Freeing your pointer only (using free(ptr)) doesn't free the originally malloced char array, but once you've done that, it's no longer valid to access any of the members of the structure (in this case, str) because the memory is no longer assigned to that process. If you try to access ptr->str at this point, the behavior is undefined.

Brenda.

| improve this answer | |
  • Thanks for your answer, Brenda, but again could you explain please what ptr -> str = s; does? – Kareem Jun 12 '14 at 8:06
  • ptr->str=s sets the member str of the struct to the value of s (ie, the address of the string). After printing it, to free the node, you should first free(ptr->str) and then free(ptr). That way, you won't have to free(s) because you've already freed it because ptr->str is the same address. I'm assuming that you are working toward some sort of linked list and your struct will eventually have more than one member, so it's more convenient to free it this way then to free(s) at the end. -Brenda. – curiouskiwi Jun 12 '14 at 8:24
  • I just thought that free(ptr) will free the struct pointed to by ptr and its members and that's sort of what I got when I tried to print ptr -> str after a call to free on ptr. I turns out that what is actually happening is that it just sets str to NULL. Thanks again, Brenda! :) – Kareem Jun 12 '14 at 8:31

You must log in to answer this question.

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