找到你要的答案

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

Q:并释放一个int *,被分配到一个char *(` malloc分配的`)调用未定义的行为吗?

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?

标题可能混淆。如果str是一个指针的malloc分配。PTR,int类型,分配给它,如下面的代码片断中解脱出来:

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

free(ptr);

我试图编译上面的代码。它只是发出警告:

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

上面的代码调用未定义的行为吗?
Does the above code snippet free the memory allocated by malloc for str?

answer1: 回答1:

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

上面的代码调用未定义的行为吗?

这取决于。

从6.3.2.3/7 C11草案:

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.

作为一个字符的排列可能不同于int,这可能是限制较少,分配一个char * PC int * PI可能导致PI对齐。

但是对于OP给出的具体例子:

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

的行为会被定义为(见改变Mann的评论)malloc()保证返回内存块对齐。

从7.22.3 C11草案:

The pointer returned [by aligned_alloc, calloc, malloc, 和 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 ...

一个例子,这将导致未定义的行为,由于错位,是:

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

上面的代码片段释放内存的malloc的STR分吗?

如果前者分配将引入未定义行为这个问题是无关紧要的,都可以与UB曾被已经发生。

如果其他现有的分配不会调用UB,调用free()将完全取消分配内存块为参考,将返回指针值从int * void *,由malloc()最初提供的,是明确的。

从C11草案6.3.2.3/7(续/):

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

从6.3.2.3/1 C11草案:

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 和 back again; the result shall compare equal to the original pointer

answer2: 回答2:

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.

不调用未定义的行为。警告只是关于不兼容的类型,你可以投。

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

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

answer3: 回答3:

Does the above code invoke Undefined Behavior?

No.

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

Yes.

Just for clarification, some notes on UB regarding dynamic allocation:

Memory returned by malloc is aligned to take any possible value. Such memory has no declared type and its effective type is set through storage.

If you do

*ptr = 42;

the first sizeof (int) bytes of the memory block will now be of type int and may only be read as such, ie

float val = *(float *)ptr;

will be UB.

However,

*(float *)ptr = 42.0;

would be legal as it re-sets the effective type, now in turn making reads through *ptr invalid.

In addition, it is always legal to access any object through pointers of type char or unsigned char.

上面的代码调用未定义的行为吗?

不.

上面的代码片段释放内存的malloc的STR分吗?

对.

只是为了澄清,在UB对于动态分配的一些笔记:

Memory returned by malloc is aligned to take any possible value. Such memory has no declared type 和 its effective type is set through storage.

如果你做的

*ptr = 42;

the first sizeof (int) bytes of the memory block will now be of type int 和 may only be read as such, ie

float val = *(float *)ptr;

将UB。

然而,

*(float *)ptr = 42.0;

将法律作为它重新设置有效的类型,现在反过来使读通过指针无效。

此外,通过指针类型char或无符号字符访问任何对象都是合法的。

answer4: 回答4:

It may invoke UB, based on endianness, alignments or such int vs char typecasting when accessed. When you do malloc all it does is return a void* which can be of any data type(and in some cases may require typecasting). It doesn't make a difference if you put a pointer in char* to int*, but there would be difference in access units, i.e in case of ints 4 bytes at a time vs in char 1 byte at a time. So, that code in your question wouldn't invoke UB, but memory accesses might.

As for second question, yes calling free on ptr will cause memory pointed by str also to be freed. Now, str would be a dangling pointer.

It may invoke UB, based on endianness, alignments or such int vs char typecasting when accessed. When you do malloc all it does is return a void* which can be of any data type(和 in some cases may require typecasting). It doesn't make a difference if you put a pointer in char* to int*, but there would be difference in access units, i.e in case of ints 4 bytes at a time vs in char 1 byte at a time. So, that code in your question wouldn't invoke UB, but memory accesses might.

至于第二个问题,是呼唤自由的PTR将导致内存被释放的STR也指出。现在,STR将悬垂指针。

c  pointers  memory  free  undefined-behavior