0

Let's say a have a function which takes in a buffer for something, and may need to allocate the memory to the buffer in the function's scope. It might look like this:

void func_with_buf( ...params..., char** buf ) {

    if ( !buf ) {
       buf = ( char** )calloc( ... );
    }

    /* more stuff here */
    ...
} 

Now, later on in this function there be another conditional statement which evaluates to false, and if false is returned in the if/conditional statement, the buf pointer-to-pointer should be freed, since nothing can be done further more in the function itself.

So, there are two approaches to this, and I'd like to know which one would be considered "safer" and more pragmatic in terms of extensibility, reuse, etc.

Approach A)

char* buf;

if ( !func_with_buf( ..., &buf ) ) {

   free( buf );
   buf = NULL;
   /* more error handling here */
}

Approach B)

char* buf; 

if ( !func_with_buf( ..., &buf ) ) {
    /* no need to free buf because func_with_buf handles deallocation internally. */
} 

Something tells me that approach A) would be the recommended way to go, but I'm curious and would like to see if I've over looked anything.

Also, if the programmer needs to free a pointer-to-pointer, is it as simple as just passing it to free(p) and it will handle it? Or do I need to cast it to a single pointer of the same type?

So many questions...

zeboidlund
  • 9,731
  • 31
  • 118
  • 180

2 Answers2

4

I think both are acceptable, provided it's made very clear in the function's description.

Personally, if I have a function that allocates memory and for whatever reason fails, I feel it has an obligation to free that memory. If the caller receives an error condition indicating that the memory is useless, they should expect that it has also been freed.

Or to put it another way, the memory is only valid if the function indicates success.

By the way, in your function you are doing this:

buf = ( char** )calloc( ... );

But I think you meant to do this:

*buf = ( char* )calloc( ... );

You are asking the caller to supply a pointer that you will modify. So they passed a pointer to their pointer, but the actual datatype they require is an array of char.

As for your last question (sorry, I didn't see it at first), no - you do not need to cast it (unless you want to cast to void*). The function free just takes a memory address and releases whatever memory was allocated there. It does not require a type.

paddy
  • 60,864
  • 6
  • 61
  • 103
4

Approach (C)

char* buf = func_with_buf( ..., buf );

in that way you pass in the original buf but return the new or buf, if something goes wrong return NULL (and clean up in the function).

AndersK
  • 35,813
  • 6
  • 60
  • 86