TempReturnBuffer


Let's say you have a function that needs to return a string.  Since a char array isn't a pass by value type, you need to reserve a block of memory to return as the string.  Using a typical char[] won't work because once it goes out of scope at the end of the function, it will be freed and lost.  You have three different options to get around this problem:

  1. malloc(1000) a chunk of memory and return the pointer to this string*
  2. Have the programmer pass a pointer to a buffer to use
  3. Use a static buffer as a temporary buffer

 

The first option is good because it's safe.  You know how big the buffer is because you ask for it from the operating system.  It's also thread safe because each time the function is called, a new buffer is called.  The downside is that unless the programmer using your function remembers to eventually call free(buffer), your function will leak memory and slowly allocate more and more temporary buffers.

 

The second approach has the advantage that you don't have to deal with the buffer at all.  You trust the users of your function to correctly allocate and pass you a pointer to a buffer of suficient size.  Granted if they pass a NULL pointer or a buffer which is too small, and all kinds of badness will ensue.  Unless they use local variables, they will probably use malloc anyways, which reintroduces the chance to forget to free() it.

 

I will argue that the third choice is the best of the three.  In your function, declare a static char buffer[1000], then return a pointer to this buffer.  Since it's static, it will not be freed when it goes out of scope and lost, but next time the function is called, it will use the same temporary buffer.  Granted this will break if used in a multithreaded program.  There is a possibility that two threads will call the function at the same time and thrash the buffer.  Using a mutex is a possible solution: It would require the caller to unlock the mutex once done, but this deadlock would be much easier to find than a malloc memory leak in the first case.

 

Code:

char * func1() {

     char *buffer = (char *)malloc(1000);

     buffer[0] = '\0'; // Initialize buffer

     // Do processing to fill buffer

     return buffer;

}

 

void func2(char *buffer) {

     // Do checks to make sure buffer isn't NULL

     buffer[0] = '\0'; // Initialize buffer

     // Do work on buffer

     return;

}

 

char *func3() {

     static char buffer[1000];

     buffer[0] = '\0'; // Initialize buffer

     // Do work on buffer

     return &buffer;

}

 

Usage:

char *output = func1();

// Use result

free(output);

 

char *output = (char *) malloc(1000); // or char output[1000];

func2(output);

// Use result

free(output);

 

char *output = func3();

// Use result

// Don't need to free, will be reused next time

 


Extensions:

If the function needs to be multithreaded, you could create multiple static char buffers[], with a mutex for each buffer, so the user would be required to unlock the mutex once done with the buffer, or else the limited number of buffers would be depleted.  If there is more threads than buffers, a calling thread that finds no buffers available should sleep or condition wait.  If there is a limited number of threads, if there are no buffers left, have it print an error message and exit(EXIT_FAILURE), or have it return an error number (Granted if they aren't using your API correctly, they likely aren't checking error codes either).

 

* Note that in all these buffers, they're shown as 1000 bytes, but this is arbitrary and can be increased or shrunk to fit your needs.

 


Sources:

Unknown