I'm not that new to coding but I faced a problem I couldn't explain to myself.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *test;
test = (char *)calloc(15, sizeof(char));
// test = "Wurstbrot";
free(test);
}
If I compile this, test
gets malloced and directly freed (what I expected).
But if I uncomment the comment, I get this error while compiling:
a.out(28953,0x104403dc0) malloc: *** error for object 0x10365cfae: pointer being freed was not allocated
a.out(28953,0x104403dc0) malloc: *** set a breakpoint in malloc_error_break to debug
zsh: abort ./a.out
When I remove the free
function, it will work again.
My question now: why is it a problem here to free an initialized pointer?
CodePudding user response:
free
must be passed a null pointer or a valid pointer to a block allocated by malloc()
, calloc()
, realloc()
, strdup()
or another heap allocation function.
If you uncomment test = "Wurstbrot";
the pointer will point to static data, the string literal "Wurstbrot"
. Passing this address to free()
has undefined behavior.
Passing test
uninitialized would have undefined behavior too. If you are lucky, this uninitialized variable might happen to contain a null pointer, thus not causing a problem with free()
... Undefined behavior is undefined, anything may happen including no visible side effect. A runtime error such as the one reported by the C library is actually quite useful to find bugs. no side effect is probably no luck in hindsight.
CodePudding user response:
When we analyze program run step by step:
A) Initialization before program starts running:
A memory space on the stack is allocated and the string "Wurstbrot" '\0' is laid on that memory space. Say, that memory allocated for string starts at AAAA:0000
; i.e. stack memory state is sth like below;
address value
AAAA:0000 W
AAAA:0001 u
AAAA:0002 r
...
AAAA:0007 o
AAAA:0008 t
AAAA:0009 0 // that's a zero
B) When program starts running:
Line 1: A pointer variable is created. This variable sits on stack and is uninitialized. For a 32 bits system, this variable sits on the stack (say, at address AAAA:0020
to AAAA:0023
and contain some garbage value like DBAC:5782
that points to some random memory.
address value
AAAA:0020 DB
AAAA:0021 AC
AAAA:0022 57
AAAA:0023 82
Line 2:
Operating system allocates a memory space (probably on the heap) with a length of 15 bytes and hands the starting value to the program (say it starts from DDDD:0000
). This value is assigned to your pointer variable and the pointer value on line 1 changes to DDDD:0000
.
address value
AAAA:0020 DD
AAAA:0021 DD
AAAA:0022 00
AAAA:0023 00
Line 3: test = "Wurstbrot";
line resets the value of the pointer to point to the memory that was allocated at step (A). From now on, your pointer variable test
do not point to the allocated memory space on the heap but the initialized memory space on the stack.
address value
AAAA:0020 AA
AAAA:0021 AA
AAAA:0022 00
AAAA:0023 00
Line 4: This line, of course, raise error. It tries to free the initialized memory space at step (A), not the memory space that was allocated at step (B)/1.
Solution:
Line 3 should read as: strcpy(test, "Wurstbrot");