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

char* f(void) {
  char *x;
  x = malloc(sizeof(char) * 4);
  strcpy(x, "abc");
  return(x);
}

int main(void) {
  char *a;
  a = f();
  printf("%s", a);
  free(a);
  return(0);
}

Does the variable x in the function have to be freed? If so, how is that possible when I need to return it?

pb2q
  • 58,613
  • 19
  • 146
  • 147
user1588871
  • 185
  • 1
  • 1
  • 4
  • 2
    Why do you put parens in the `return` expression? – ouah Aug 09 '12 at 22:48
  • 1
    @ouah: A matter of style. I don't personally, but the project that I work on every day does. It also does things like `if(someBoolean == true)` which I can't stand, but I know that the original programmer was not ignorant of the boolean type (he's a very bright guy), he just prefers it. – Ed S. Aug 09 '12 at 22:52
  • 1
    Whenever you feel the urge to return a pointer to dynamically allocated data, you should ask yourself: "Why am I designing the program so that the allocation and freeing are in different code modules?", "Why isn't the code that understands the nature of the data and the code using the data in the same module?" and similar questions related to proper OO design. – Lundin Aug 10 '12 at 06:50

6 Answers6

17

Does the variable x in the function have to be freed?

Yes (kinda, see my later comment). Every call to malloc requires a later call to free. Otherwise, you have a leak. Remember though; you are not "free[ing] x", you are freeing the memory that x refers to.

When you return x a copy of the value (an address) of x is made and returned to the caller. x was declared with automatic storage duration. It is the memory it refers to that must be freed.

If so how is that possible when I need to return it.

Your design has placed the onus on the caller to free the memory. You have already done this in main. Of course, using this method requires that you document the function so that users of your code know that they are receiving an address to memory which was dynamically allocated.

A better approach (IMO) is to take a buffer as an input parameter. Now it is very clear who is responsible for managing this memory (i.e., the caller). Perhaps I don't even want to dynamically allocate it. With this design it is my choice.

void f(char *buf, size_t buf_size) {
  strncpy(buf, "abc", buf_size - 1);
  buf[buf_size-1] = '\0';
}

On a side note, you should always be checking the return value of malloc. It can fail, in which case a null pointer will be returned. Also, sizeof(char) is guaranteed to be 1 by the standard, so you can remove that bit and just say malloc(n).

Ed S.
  • 122,712
  • 22
  • 185
  • 265
2

Yes you need to free, but it's already being freed when you do free(a); in main (since a is assigned to equal x in the line a = f();).

SamYonnou
  • 2,068
  • 1
  • 19
  • 23
1

Yes it should be freed by the caller. Such as the free in your main.

When you return x in the function f, a copy of the address is passed back to the caller. The caller can call free on that address.

pb2q
  • 58,613
  • 19
  • 146
  • 147
1

x is destroyed after you exit the function. The value of x is an address that points to a dynamically allocated object. The object still exists after you exit the function.

To free the dynamically object you have to pass the value of x that is returned by the f function to the free function.

ouah
  • 142,963
  • 15
  • 272
  • 331
0

When you call malloc it allocates memory and returns the initial address of that memory block.

In your case you return this address back to the callee, now the callee, main, is responsible for deallocating it.

The only thing required to deallocate a memory block is the initial address, AFIK the OS is in charge of allocating/freeing memory it uses fairly complex algorithms, but the programs only need to keep track the initial memory address. This address can be stored or moved around just like any other integer value because in 32 bit systems thats all it is just an int value.

Samy Vilar
  • 10,800
  • 2
  • 39
  • 34
0

You code work well, you freed a which is the string malloced by f.

TOC
  • 4,326
  • 18
  • 21