释放一个铸造的指针

我想知道是否可以释放()一个指向另一个类型的指针。 例如,如果我这样做:

char *p = malloc (sizeof (int));
int *q = (int *)p;
free (q);

我在gcc(-Wall)上没有任何警告。

在Linux上,free页面上的man页面表示,通过malloc(),calloc()或realloc()不返回的指针调用free是非法的。 但是如果指针被转换为另一种类型,会发生什么?

我问这是因为我读了C标准不需要不同的指针类型(例如int *和char *)具有相同的大小,并且我不明白这是如何可能的,因为它们都需要转换为void *以调用malloc / free函数。

上述代码是否合法?

谢谢。


这可能是安全的,但并不绝对保证安全。

在大多数现代系统中,所有指针(至少所有对象指针)具有相同的表示形式,并且从一种指针类型转换为另一种指针类型只是重新解释组成表示的位。 但C标准并不能保证这一点。

char *p = malloc (sizeof (int));

这给你一个char*指针,指向sizeof (int)字节的数据(假定malloc()成功。)

int *q = (int *)p;

这将char*指针转换为int*指针。 由于int大于char ,因此int*指针可能需要较少的信息来指示它指向的内容。 例如,在一个面向字的机器上,一个int*可能指向一个单词,而一个char*必须包含一个字指针和一个偏移量,该偏移量指示该字指向哪个字节。 (我实际上在一个系统Cray T90上工作,就像这样工作)。因此,从char*int*的转换实际上可能会丢失信息。

free (q);

由于free()接受一个类型为void*的参数,因此参数q将从int*隐式转换为void* 。 有一个在语言标准不保证转换char*指针int* ,然后转换结果void* ,为您提供了相同的结果转换char*直接到void*

另一方面,由于malloc()总是返回一个指向正确的指向任何类型的指针,即使在int*char*有不同表示的系统上,在这种情况下也不太可能导致问题。

因此,您的代码几乎可以确定在任何您可能使用的系统上正常工作,即使在您可能从未见过的异国系统上也可能正常工作。

不过,我建议您通过保存原始指针值(类型为char* )并将其传递给free()来编写可以轻松演示的代码。 如果需要几段文字来证明你的代码几乎可以肯定是安全的,那么简化你的假设可能会为你节省长期的工作量。 如果程序中出现其他问题(请相信我,有些事情会发生),那么尽量不要担心可能导致错误的原因。

你的代码更大的潜在问题是你不检查malloc()是否成功。 如果没有做任何失败的事情(转换和free()调用都可以使用空指针),但是如果你引用你分配的内存可能会遇到麻烦。

更新:

你问你的代码是否合法; 你没有问过这是不是做你正在做的最好的方法。

malloc()返回一个void*结果,它可以通过赋值隐式转换为任何指向对象的类型。 free()需要一个void*参数; 您传递给它的任何指向对象类型的参数将被隐式转换为void* 。 这种往返转换( void* to something_else*void* )是安全的。 除非你正在进行某种类型的双击(将两个不同类型的数据解释为同一块),否则不需要任何演员。

而不是:

char *p = malloc (sizeof (int));
int *q = (int *)p;
free (q);

你可以写:

int *p = malloc(sizeof *p);
...
free(p);

注意在malloc()的参数中使用sizeof *p 。 这可以让你知道任何p点的大小,而不必明确地引用它的类型。 它避免了意外使用错误类型的问题:

double *oops = malloc(sizeof (int));

编译器可能不会提醒你。


是的,这是合法的。 free()需要一个void指针( void* ),所以类型不重要。 只要传递的指针由malloc/realloc/calloc返回,它就是有效的。


是的,指针没有改变,转换只是编译器如何解释一堆位。

编辑:malloc调用返回内存中的地址,即32(或64)位数。 该投射只告诉编译器如何解释存储在该地址的值,它是一个浮点数,整数,字符串等,并且当你对地址进行算术运算时,它应该插入多大的单位。

链接地址: http://www.djcxy.com/p/28357.html

上一篇: free a casted pointer

下一篇: casting void pointers