Freeing memory that is not allocated dynamically can cause a lead to serious errorerrors. The specifics and extent of damage caused by specific consequences of this error depends on the compiler in use, but can range ranges from nothing to unintended and unexpected abnormal program termination. Regardless of the implementationcompiler, avoid calling free()
on non-dynamic memory should be avoided.
A similar situation arises when realloc()
is supplied a pointer to non-dynamically allocated memory. The realloc()
function is used to resize a block of dynamic memory. If realloc()
is supplied a pointer to memory not allocated by another dynamic a memory allocation routinefunction, such as{{malloc(), a series error could occur}}, the program may also terminate abnormally.
Non-compliant Code Example 1
In this example, a file is opened for reading. If the file is opened successfully, then a block of memory is allocated on the heap with by malloc()
and pointed to referenced by str
. A message indicating that the file was opened properly is copied into a block of dynamic memory pointed to the dynamically-allocated memory referenced by str
, and the message is printed via the log_it() function. After log_it() is called. Afterwards, the dynamic memory is freed. However, if deallocted by calling free()}. If the file does not open correctly, however,
then {{str
will be is set to a non-dynamic string literal. When this str is freed, since it points to non-dynamic memoryBecause str
now references memory that was not dynamically allocated, an error will occur when this memory is freed.
Code Block |
---|
#include <stdlib.h> #include <stdio.h> void log_it(char *msg_buf) { printf("LOG: %s\n", msg_buf); } int main(void) { FILE *file = NULL; char *str = NULL, *fname="~/config_file"; size_t size = 100; file = fopen("~/config_file","r"); if (file != NULL) { str = (char *)malloc(size); snprintf(str, size, "File %s opened properly", fname); log_it(printf("LOG: %s\n", str); } else { str = "ERROR OPENING FILE OPENED"; log_it(printf("LOG: %s\n", str); } free(str); return 0; } |
Compliant
...
Solution 1
This compliant example is very similar to the non-compliant example above. The only modification is In the compliant solution, the call to free()
has been moved inside the conditional statement to ensure that only dynamic memory is freed.
Code Block |
---|
#include <stdlib.h> #include <stdio.h> void log_it(char *msg_buf) { printf("LOG: %s\n", msg_buf); } int main(void) { FILE *file = NULL; char *str = NULL, *fname="~/config_file"; size_t size = 100; file = fopen("~/config_file","r"); if (file != NULL) { str = (char *)malloc(size); snprintf(str, size, "File %s opened properly", fname); log_it(printf("LOG: %s\n", str); free(str); /* only dynamic memory is freed */ } else { str = "ERROR OPENING FILE OPENED"; log_it(printf("LOG: %s\n", str); } return 0; } |
Non-compliant Code Example 2
This example attempts to resize the string referenced by buf
to make enough room in buf to append another the string , line
. However, once in the function append()
, there is no way to determine how buf
was allocated. When realloc() is called on buf, since buf does not point to dynamic memory, an error may occur.
Code Block |
---|
void append(char *buf, size_t count, size_t size) { char *line = " <- THIS IS A LINE"; int line_len = strlen(line); if ((count + line_len) > size) { buf = realloc(buf,count+line_len); size = count + line_len; } strncat(buf,line,line_len); } int main(void) { append("AAAAA",5,6); return 0; } |
Compliant
...
Solution 2
Correcting the above example is an exercise in documentation. Since realloc is used to resize the memory pointed to by buf, the function append has the precondition that buf must point to dynamically allocated memory.
...