1

I wanted to know what happens in this piece of code?

Here, I have a variable f2 in func2 where it is allotted a block of space via malloc and a variable f1 in func1 which is also allotted a block of space via malloc.

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

char* func2(){
    char *f2 = (char *)malloc (sizeof(char) * 10);
    
    f2[0] = '1';
    f2[1] = '2';
    f2[2] = '3';
    f2[3] = '\0';
    
    return f2;
}

char* func1(){
    char *f1 = (char *)malloc (sizeof(char) * 10);
    
    f1 = func2();
    
    return f1;
}

int main()
{
    printf("String: %s", func1());

    return 0;
}

Now, since I have allotted a heap memory in func2, and func1 is calling it, then func1 should free that memory. But I am allocating the returned value to one of func1's local variable f1 and would return that variable to main function I can't delete it in func1.

So, how will I free the memory that was allocated in func2. Is the heap memory space for f1 in func1 and f2 in func2 the same?

Developer
  • 425
  • 3
  • 15
  • 3
    You have a memory leak. – Fiddling Bits Nov 04 '20 at 13:46
  • @FiddlingBits How could I tackle this problem then? – Developer Nov 04 '20 at 13:47
  • What is a "malloc variable"? Do you mean a variable which is assigned the value returned by malloc? If you assign it to another variable, exactly the same thing happens as when you assign the value returned by any other function. – William Pursell Nov 04 '20 at 13:47
  • [don't cast the result of `malloc`](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc), if the resource you're using is teaching you to do this, throw it into the garbage. – Chase Nov 04 '20 at 13:50
  • "What happens if I set one malloc variable equal to another malloc variable" @WilliamPursell I refer "one malloc variable" as f2 and "another malloc variable" as f1. – Developer Nov 04 '20 at 13:50
  • I didn't know that not casting was also an option @Chase – Developer Nov 04 '20 at 13:54
  • In `char *f1` f1 is a container (like all variables) called a pointer. A pointer contains an address. If you replace that address with another one, it's lost and you can't free it anymore (*free()* needs an address that was allocated with the malloc() family). – Déjà vu Nov 04 '20 at 13:58

2 Answers2

2

If you expect func1 to free anything, it should call free:

char * 
func1(void)
{
    char *f1 = malloc (sizeof *f1 * 10);
    free(f1);
    f1 = func2();
    
    return f1;
}

If you do not explicitly free the memory, then you have a memory leak, since overwriting f1 with the result of func2 discards the previous value of f1 and your program no longer knows the value of the address that was previously allocated, so you will not be able to free it.

There is no relationship between the values returned by malloc. Consider:

int x = 5;
x = 7;

What happened to the 5? It got discarded. There is nothing magical about an address returned by malloc. If you assign a different value to f1, the previous value is discarded.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
  • I have read that it is not legal to return pointer to a local variable. To return a local variable, one of the options is to make it in the heap memory (Correct me, if I am wrong). If I free(f1), will still it be legal to return f1? – Developer Nov 04 '20 at 14:19
  • `f1` is a local variable, so it is perfectly safe to return it. It would not be safe to `return &f1`, which would be a pointer to a local variable. If you `free(f1)`, it would be perfectly safe (but useless) to `return f1`. Since you assign a different value to `f1` after you free it, it is not useless to return that value. Remember `return f1` does not return the address of `f1`, it returns the value of `f1`. The code given here free's a different address than the one returned by `func2`. – William Pursell Nov 04 '20 at 16:17
  • But after the function `func1` has completed its execution, will not the local variables also be gone? That is why I was trying to allocate a heap memory to it. But now we free that memory. So, now the `main` function should not be able to get the value returned by `func1`? I am very confused with these topics like what should a function return, what variables are gone after the function has executed and so on. Could you suggest a good and easy to understand resource for the same? – Developer Nov 04 '20 at 16:30
  • 1
    Yes, the local variables are gone after the function returns. But the value of `f1` is an address on the heap, and it is completely valid. It is perfectly safe to write `int foo(void) { int x = 5; return x;}` – William Pursell Nov 04 '20 at 16:32
  • 1
    It would not be safe to write `int foo(void) { int x = 5; return &x; }` Similarly, it would be invalid to write `int func2(void) { char f2[] = "123"; return f2;}`, but it is perfectly safe to write `int func2(void) { char *f2 = "123"; return f2;}` In the `char f2[]` case, func2 is returning the address of a local variable. In the `char *f2` case, func2 is returning the address of a string literal, which persists after the function returns. – William Pursell Nov 04 '20 at 16:36
  • Thank you, this has cleared a lot of doubts that I had. Could you also suggest some resources for the same? Thank you. – Developer Nov 04 '20 at 16:50
2

When you malloc a chunk of memory, that chunk of memory stays there until you explicitly call free on it. malloc returns a pointer to that chunk of memory, and if you overwrite the pointer with a pointer to a different chunk of memory, it doesn't get rid of the first chunk of memory. You can either free the old f1 in func1 like William Pursell suggested, or you could just not allocate a second chunk of memory in the first place, since allocating more unused memory does nothing:

char* func1() {
    char* f1 = func2();
    return f1;
}

As a side note, you should never cast the result of malloc.

Aplet123
  • 33,825
  • 1
  • 29
  • 55