1

Can I return an array that is created dynamically (using malloc) inside a function back to its caller?

I know that returning a statically allocated array is wrong because the stack unwinds as the function returns and variable is no longer valid but what about a dynamically allocated variable?

3
  • You can return a pointer, or was there something more complicated that you had in mind? Commented Feb 3, 2011 at 1:45
  • 3
    Static allocation != automatic allocation. Local variables have automatic storage duration. Static storage duration means that the object exists for the entire time the program is running (these objects are declared either at file scope or using static in a function). Commented Feb 3, 2011 at 1:47
  • No that is just what I wanted to do Commented Feb 3, 2011 at 1:57

4 Answers 4

5

Returning anything allocated with malloc is fine, as long as whoever uses your function takes care of free()ing it when they're done. malloc allocates on the heap which is essentially global within your program.

Sign up to request clarification or add additional context in comments.

3 Comments

If I don't free something I allocate using 'malloc' and the program terminates then the memory is freed by itself right?
@ShyamLovesToCode: Yes, unless your OS (or something closely related to it) is broken, it will get freed. It's "neater" to free the stuff you use by hand, though.
Of course it will get "freed" at process exit. But depending on your usage, if you do not free the allocated structure during runtime, you will "leak" memory and may run out.
3

As others have noted, you can in fact return a char pointer. However, another common method is for the caller to pass in the pointer for the method to fill along with a length parameter. This makes it so the function responsible for allocating the memory will also be the same function responsible for freeing the memory, which can make memory leaks easier to see. This is what functions such as snprintf and strncpy do.

/* Performs a reverse strcpy. Returns number of bytes written if dst is
 * large enough, or the negative number of bytes that would have been
 * written if dst is too small too hold the copy. */
int rev_strcpy(char *dst, const char *src, unsigned int dst_len) {
    unsigned int src_len = strlen(src); /* assumes src is in fact NULL-terminated */
    int i,j;

    if (src_len+1 > dst_len) {
        return -(src_len+1);  /* +1 for terminating NULL */
    }

    i = 0;
    j = src_len-1;
    while (i < src_len) {
        dst[i] = src[j];
        ++i;
        ++j;
    }
    dst[src_len] = '\0';

    return src_len;
}

void random_function() {
    unsigned int buf_len;
    char *buf;
    int len;
    const char *str = "abcdefg";

    buf_len = 4;
    buf = malloc(buf_len * sizeof(char));
    if (!buf) {
        /* fail hard, log, whatever you want */
        return;
    }

    /* ...whatever randomness this function needs to do */

    len = rev_strcpy(buf, str, buf_len);
    if (len < 0) {
        /* realloc buf to be large enough and try again */
        free(buf);
        buf_len = -len;
        buf = malloc(buf_len * sizeof(buf));
        if (!buf) {
            /* fail hard, log, whatever you want */
            return;
        }
        len = rev_strcpy(buf, str, sizeof(buf));
    }

    /* ... the rest of the randomness this function needs to do */

    /* random_function has allocated the memory, random_function frees the memory */
    free(buf); 
}

This can lead to some overhead though if you don't know how big a buffer you'll need and need to call the function twice, but often the caller has a good idea to how large the buffer needs to be. Also it requires a little more logic to ensure the function doesn't overrun the given buffer. But it keeps the responsibility of freeing the memory with whatever is allocating the memory, while also allowing the option to pass local stack memory.

Example just returning the char*:

/* Performs a reverse strcpy. Returns char buffer holding reverse copy of
 * src, or NULL if memory could not be allocated. Caller is responsible
 * to free memory. */
char* rev_strcpy(const char *src) {
    unsigned int src_len = strlen(src); /* assumes src is in fact NULL-terminated */
    char *dst;
    int i,j;

    dst = malloc((src_len+1) * sizeof(char));
    if (!dst) {
        return NULL;
    }

    i = 0;
    j = src_len-1;
    while (i < src_len) {
        dst[i] = src[j];
        ++i;
        ++j;
    }
    dst[src_len] = '\0';

    return dst;
}

void random_function() {
    char *buf;
    const char *str = "abcdefg";

    /* ...whatever randomness this function needs to do */

    buf = rev_strcpy(str);        
    if (!buf) {
        /* fail hard, log, whatever you want */
        return;
    }

    /* ... the rest of the randomness this function needs to do */

    /* random_function frees the memory that was allocated by rev_strcpy */
    free(buf); 
}

Comments

0

Yes you can. Just malloc() the array inside your function and return the pointer.

BUT, the caller needs to understand it needs to be freed at some point, or you'll have a memory leak.

Comments

0

You can certainly return an array allocated with malloc, but you have to make sure the caller of the function eventually releases the array with free; if you don't free a malloc'd array, the memory remains "in use" until program exit.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.