5

asprintf says

The functions asprintf() and vasprintf() are analogs of sprintf(3) and vsprintf(3), except that they allocate a string large enough to hold the output including the terminating null byte, and return a pointer to it via the first argument. This pointer should be passed to free(3) to release the allocated storage when it is no longer needed.

Here is my C code

void function(){
    char *out = NULL;
    int parts[16] = {1,2,05,003};
    asprintf(&out, "%d.%d.%d.%d", parts[0], parts[1], parts[2], parts[3]);
  //  free(out);
}

int main(void){
    function();
    return 0;
}

When the function is monitored on the debug mode, I see that the variable is already destroyed when it returns from the function. Why I don't need to free() the code above?

Could you tell me in what cases of asprintf I need to use free?

btw, I have "gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1)"

enter image description here enter image description here

4

4 回答 4

11

You need to call free().

The variable leaves the scope, so the actual value of the variable (the address that free() needs) is lost at that point, creating a memory leak.

The free() function is interested in the address of memory previously returned by malloc() or some other heap allocation call, not at all in your particular variable.

You could do:

char *out = NULL, *a, *b, *c, *d, *e;
int parts[16] = {1,2,05,003};
asprintf(&out, "%d.%d.%d.%d", parts[0], parts[1], parts[2], parts[3]);
a = b = c = d = e = out;

and that's just five more variables holding copies of the same address going out of scope. The heap subsystem (as reached through the malloc()/free() calls) knows nothing about this, of course.

于 2013-06-28T13:47:46.707 回答
6

It seems you don't quite understand what pointers are, what local variables are, and what allocating memory does.

In your function() you have a variable out. You've declared that it is a char pointer.

You're passing a pointer to that variable to asprintf(). This is so asprintf can allocate some memory on the heap, and store the address of that memory location in out. This is called a "pointer to a pointer" and why the signature of asprintf() appears as asprintf(char **ret, .. ) - note the double **

out now contains the address of the allocated memory. You then leave function(). out ceases to exist because it's a local variable and only exists on the stack. The address that was previously contained in it is lost but the memory that was allocated on the heap that address referred to remains allocated ... and you have a memory leak.

You need to free() that memory before you lose the address and it becomes forever beyond your reach.

于 2013-06-28T13:55:24.070 回答
5

Could you tell me in what cases of asprintf I need to use free?

Every time, except when asprintf returns -1.

If memory allocation wasn't possible, or some other error occurs, these functions will return -1, and the contents of strp is undefined.

You can analyze valgrind ouput for instance.

  • Without free call:

==3711== HEAP SUMMARY:
==3711== in use at exit: 8 bytes in 1 blocks
==3711== total heap usage: 2 allocs, 1 frees, 108 bytes allocated

Obviously, there is a memory leak.

  • With free call:

==3722== HEAP SUMMARY:
==3722== in use at exit: 0 bytes in 0 blocks
==3722== total heap usage: 2 allocs, 2 frees, 108 bytes allocated

于 2013-06-28T13:49:42.783 回答
4

out is "destroyed", but not what is was pointing to. The latter is still allocated, but any reference to it is lost. You can consider this a memory leak.

To avoid such call free(out) before leaving function().

An alternative solution would be to return the value of outfrom function, so the caller could still use the memory referenced. On the other hand the caller also then takes the responsibility to free the this memory:

char * function(void) {
    char * out = NULL;
    int parts[16] = {1, 2, 05, 003};

    asprintf(&out, "%d.%d.%d.%d", parts[0], parts[1], parts[2], parts[3]);

    return out;
}

int main(void) {
    char * out = function();
    if (NULL != out)
    {
      printf("5s\n", out);
      free(out);
      out = NULL;
    }

    return 0;
}
于 2013-06-28T13:49:47.990 回答