我想知道free()指针是否可以转换为另一种类型.例如,如果我这样做:
char *p = malloc (sizeof (int));
int *q = (int *)p;
free (q);
Run Code Online (Sandbox Code Playgroud)
我没有收到关于gcc(-Wall)的警告.
在linux上,free上的手册页说,在malloc(),calloc()或realloc()没有返回的指针上调用free是违法的.但是如果指针被转换为中间的另一种类型会发生什么?
我问这个是因为我读到C标准不要求不同的指针类型(例如int*和char*)具有相同的大小,我不明白这是如何可能的,因为它们都需要可转换为void*为了调用malloc/free函数.
以上代码是否合法?
它可能是安全的,但并不是绝对保证安全.
在大多数现代系统中,所有指针(至少所有对象指针)具有相同的表示,并且从一种指针类型转换为另一种指针类型只是重新解释构成表示的位.但C标准并不能保证这一点.
char *p = malloc (sizeof (int));
Run Code Online (Sandbox Code Playgroud)
这为您提供了char*指向sizeof (int)数据字节的指针(假设malloc()成功.)
int *q = (int *)p;
Run Code Online (Sandbox Code Playgroud)
这会将char*指针转换为int*指针.由于int大于char,int*指针可能需要较少的信息来指示它指向的内容.例如,在面向字的机器上,一个int*可能指向一个单词,而一个char*必须包含一个单词指针和一个偏移量,指示它所指向的单词中的哪个字节.(我实际上已经开发了一个系统,Cray T90,就像这样工作.)所以从转换char*到int*实际上可能会丢失信息.
free (q);
Run Code Online (Sandbox Code Playgroud)
由于free()采用了类型void*的参数,因此参数q被隐式转换int*为void*.在语言标准中无法保证将char*指针转换为int*然后将结果转换为void*,可以得到与char*直接转换为a相同的结果void*.
在另一方面,由于malloc()始终返回被正确的对齐指向任何类型,甚至在一个系统,其中一个指针int*,并char*有不同的表示,这是不太可能导致这种特殊情况下的问题.
因此,您的代码几乎肯定可以在您可能正在使用的任何系统上正常工作,甚至非常可能在您可能从未见过的异国情调的系统上正常工作.
尽管如此,我仍然建议您编写可以轻松演示的代码,方法是保存原始指针值(类型char*)并将其传递给free().如果需要几段文本来证明您的代码几乎肯定是安全的,那么从长远来看,简化您的假设可能会节省您的工作量.如果你的程序中出现了其他问题(相信我,会发生一些事情),最好不要担心一个可能的错误来源.
您的代码更大的潜在问题是您不检查是否malloc()成功.你没有做任何失败的事情,如果没有(转换和free()调用都没有空指针),但如果你参考你分配的内存,你可能会遇到麻烦.
更新:
你问你的代码是否合法; 你没有问这是否是做你正在做的事情的最佳方式.
malloc()返回一个void*结果,该结果可以通过赋值隐式转换为任何指向对象的指针类型.free()需要一个void*参数; 传递给它的任何指向对象的类型参数都将被隐式转换为void*.此往返转换(void*到something_else*到void*)是安全的.除非你正在进行某种类型的惩罚(将相同的数据块解释为两种不同的类型),否则不需要任何强制转换.
而不是:
char *p = malloc (sizeof (int));
int *q = (int *)p;
free (q);
Run Code Online (Sandbox Code Playgroud)
你可以写:
int *p = malloc(sizeof *p);
...
free(p);
Run Code Online (Sandbox Code Playgroud)
注意sizeof *p在参数中使用malloc().这为您提供了任何p点的大小,而无需明确地引用其类型.它避免了意外使用错误类型的问题:
double *oops = malloc(sizeof (int));
Run Code Online (Sandbox Code Playgroud)
哪个编译器可能不会警告你.