Question

Let's say we have the following scenario.

char* halfString(char* input) {
    char* output = malloc(strlen(input));
    int i = 0;
    for(i = 0; i < strlen(input); i++)
        output[i] == input[i];
    output[i] = '\0';
    return output;
}

int main() {
    char* input = "Hello";
    char* output = halfString(input);
    printf("%s\n",output);
    free(output);
} 

Will the call "free(output)" free the memory of char* output that is local to main and free the memory of the char* output local to halfString()? OR is there still a memory leak for the char* output local to halfString()?

Any help is appreciated.

Was it helpful?

Solution

There is no memory leak.

You seem to be confused, though, about how heap allocation works. There is only one chunk of memory being allocated here, and it is not "local" to either halfString() or to main(). The allocated chunk exists in the heap, and is not scoped to a particular code block.

malloc() returns a pointer to it. You then return that pointer back to main(), but the value of the pointer is still the same: it points to the same address in memory, the same chunk of heap. main() then properly frees it.

As a design consideration, this is often not the best thing to do. In general, a caller may not necessarily know that the pointer returned by halfString() points to a chunk that was allocated with malloc() and that they need to free() it. This would have to be very clearly and carefully documented. A better solution might be to provide a freeHalfString() function which does the freeing; then from a maintenance standpoint, those two functions can be put in the same place and maintained concurrently, so that the caller doesn't need to worry about how the buffer was allocated, or how to free it.

(As others have pointed out, you also have a buffer overflow because you need to allocate strlen(input) + 1 bytes to include the NULL terminator.)

OTHER TIPS

The code is mostly correct, because malloc() puts memory on the heap and free() frees it. It does not matter which functions they get called from.

That said, there is an important off-by-one error:

char* output = malloc(strlen(input) + 1); // Don't forget +1

The strlen() function returns the number of characters in the string, not including the terminator.

These errors can be often caught automatically by using certain tools like Mudflap (compile with -fmudflap, if using GCC) and Valgrind.

Algorithmic complexity

There is a problem with the algorithmic complexity of your code, which will probably disappear with good compilers when optimization is enabled.

for(i = 0; i < strlen(input); i++)

This will call strlen(), which is O(N), and it will call strlen() O(N) times, giving O(N2) asymptotic performance. We can do better, here are two fixes:

// Version 1
size_t i, n = strlen(input);
for (i = 0; i < n; i++)
    ...

// Version 2
size_t i;
for (i = 0; input[i] != '\0'; i++)
    ...

You seem to be confusing two related items: buffers, and pointers. A buffer is a block of memory which, in the context of your question, is allocated using malloc(). A pointer is related in that it points to a buffer, but it's not the buffer itself.

In your halfString() function, you allocate a buffer, and you store the address of (pointer to) that buffer in your local output.You then return it to the caller, main(), which coincidentally has a variable of the same name which will point to the same buffer.

Now, in main(), when you free(output); you're not freeing a pointer, you're freeing the buffer that pointer points to. It doesn't matter where the buffer was allocated, it only matters that the buffer was allocated (and not already freed). After this call your main function's output variable still exists, and it still has an address to what was once a valid buffer -- but that buffer must not be used of course, since it's no longer valid.

Now as to your question "Is there a memory leak?" -- You've malloc'd a single buffer, then you free'd that same buffer, so no link. Always properly pair a malloc with a free, and you'll be in good shape.

The free() will free the memory allocated in called function itself. it is not local to any function because malloc allocates memory on heap.
what you call as local memory is on stack that will be freed when function returns.
So what allocation done using malloc is on heap and the procedure you used will free memory allocated in called function.

This code will work correctly (if the off-by-one error others mention is fixed). The call in main will free the memory allocated in halfString.

There is no "memory of output that is local to main". What is local to main is the output pointer, which was allocated on the stack and will go out of scope when main exits.

There is no memory leak. System knows how much memmory is associated with pointer, and since you can not free part of memory block allocated with malloc, it will free all.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top