I\'m doing a lesson from the Learn C the Hard way online course. In the code sample below, I don\'t understand why the two free()
calls are necessary. I
strdup(3) is documented as
The strdup() function returns a pointer to a new string which is a
duplicate of the string s. Memory for the new string is obtained
with malloc(3), and can be freed with free(3).
BTW, as Matt McNabb commented, strdup
is standard in Posix, not in the C99 language specification.
Of course free
only releases the memory zone that you pass it (it does not magically and indirectly free any zone pointed inside the memory zone you pass it). Again, free(3) says:
The free() function frees the memory space pointed to by ptr, which
must have been returned by a previous call to malloc(), calloc() or
realloc(). Otherwise, or if free(ptr) has already been called
before, undefined behavior occurs. If ptr is NULL, no operation is
performed.
Read much more about C dynamic memory allocation. If you don't like that, learn about garbage collection. With C on Linux and some other systems, you could consider using Boehm's conservative garbage collector. You'll then use GC_MALLOC
and/or GC_MALLOC_ATOMIC
instead of malloc
, and GC_STRDUP
instead of strdup
and you won't bother about free
(you might sometimes use GC_FREE
if wanted). I find it very useful, but it does have some drawbacks (a bit slower than malloc
, and no explicit guarantee about releasing memory...).
Read about memory corruption, and memory leaks
BTW, you should first compile your program with all warnings and debug info (e.g. gcc -Wall -g
). Then you could use your debugger (gdb
), set a breakpoint in malloc
after main
has been reached, and see when malloc
is called. You'll see that strdup
is calling malloc
....
FYI, on Linux, malloc
is implemented using mmap(2) -and sometimes the old sbrk(2)- syscalls -to get "large" memory regions (of several kilobytes or even megabytes), and free
may sometimes call munmap(2) -for these large regions- but most often it justs mark a freed block as reusable, so that block could be reused in some future calls to malloc
. Hence a program doing malloc
and free
might not release all it previously used memory to the kernel. See also this question about memory fragmentation.
On some operating systems (e.g. Linux) you could compile your C code (using GCC) using gcc -Wall -Wextra -g
then use the valgrind
tool at runtime. It slows down the execution, but it is helpful in finding bugs like some memory leaks and some buffer overflow. With a recent GCC or Clang compiler, you could also use -at compile time- its address sanitizer (instrumenting the generated code).
You might also read the GC handbook, related to memory allocation and garbage collection algorithms.