Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does freeing an int* which was assigned to a char* (allocated by `malloc`) invoke Undefined Behavior?

The title maybe confusing. Suppose str is a pointer allocated by malloc. ptr, of type int*, is assigned to it and is freed as shown by the code snippet below:

char* str = malloc(64);
int* ptr = str;

free(ptr);

I've tried to compile the above code. It just gives a warning:

source_file.c: In function ‘main’:
source_file.c:10:16: warning: initialization from incompatible pointer type
     int* ptr = str;
                ^

Does the above code invoke Undefined Behavior?
Does the above code snippet free the memory allocated by malloc for str?

like image 785
Spikatrix Avatar asked May 02 '15 08:05

Spikatrix


People also ask

What is the difference between malloc and free in C++?

The memory allocated using functions malloc() and calloc() is not de-allocated on their own. Hence the free() method is used, whenever the dynamic memory allocation takes place. It helps to reduce wastage of memory by freeing it. Syntax: free(ptr); Example:

What is “malloc” and “alloc”?

Let’s look at each of them in greater detail. The “malloc” or “memory allocation” method in C is used to dynamically allocate a single large block of memory with the specified size. It returns a pointer of type void which can be cast into a pointer of any form.

What happens when a pointer is returned from malloc ()?

Notice how void pointer returned from the malloc () function is typecasted and then assigned to p. Memory allocated contains garbage value so do not try to dereference it before assigning proper values to it.

What happens when malloc () fails to allocate memory?

In line 15, the if condition checks whether the pointer returned by malloc () is null pointer or not. If p is NULL then memory allocation failed and the program terminates.


2 Answers

Does the above code invoke Undefined Behavior?

It depends.

From C11 draft 6.3.2.3/7:

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned) for the referenced type, the behavior is undefined.

As the alignment for a char might be different from an int, that is probably less restrictive, assigning a char * pc to an int * pi might lead to pi being misaligned.

However for the specific example given by the OP:

char * pc = malloc(64);
int * pi = pc;

the behaviour would be defined, as (See Alter Mann's comment) malloc() is guaranteed to return a block of memory properly aligned.

From C11 draft 7.22.3:

The pointer returned [by aligned_alloc, calloc, malloc, and realloc] if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement ...

An example which would lead to undefined behaviour, due to misalignment, is:

char * pc = malloc(64);
int * pi = pc + 1;

Does the above code snippet free the memory allocated by malloc for str?

In case the former assignment would have introduced undefined behaviour this question is irrelevant, as anything could happen with UB having been invoked already.

If else the prior assignment wouldn't have invoked UB, the call to free() would perfectly de-allocate the block of memory referenced, as converting back the pointer value from int * to void *, as originally provided by malloc(), is well defined.

From C11 draft 6.3.2.3/7 (cont/):

Otherwise, when converted back again, the result shall compare equal to the original pointer

and

From C11 draft 6.3.2.3/1:

A pointer to void may be converted to or from a pointer to any object type. A pointer to any object type may be converted to a pointer to void and back again; the result shall compare equal to the original pointer

like image 153
alk Avatar answered Nov 09 '22 13:11

alk


No. It doesn't invoke undefined behaviour. The warning is simply about incompatible types which you could cast.

char* str = malloc(64);
int* ptr = (int*) str;
free(ptr);

free does take a void pointer and the above has no problems. However, using the result of such a value may invoke undefined behaviour due to alignment of int type and char type. As such the conversion of char* to int* itself doesn't lead to undefined.

like image 43
P.P Avatar answered Nov 09 '22 13:11

P.P