C:自动变量免费通话?

int main() { int x = 0; free(x); } 

这编译并且似乎是无操作。 究竟发生了什么? 是这个行为定义的?

谢谢!

不,行为未定义。 而且,代码不应该编译。

首先,代码不应该编译,因为它包含约束违规。 作为free的操作数传递的表达式具有int类型。 free的参数有void *类型。 int值可以隐式转换为void * type的唯一情况是int值是值为0的积分常量表达式(ICE)。 在你的情况下, x不是ICE,这意味着它不能隐式转换为void * 。 您的代码编译的唯一原因是,由于历史原因(支持遗留代码),您的编译器会悄悄地忽略free(x)调用中出现的约束违规。 我敢肯定,如果你提高编译器中的警告级别,它会抱怨(至少有警告)。 一个迂腐的编译器会立即发出一个错误的free(x)调用。 尝试使用Comeau Online,例如在C89 / 90模式下:

 "ComeauTest.c", line 6: error: argument of type "int" is incompatible with parameter of type "void *" free(x); ^ 

(另外,你还记得在free电话之前加入stdlib.h吗?)

其次,让我们假设代码编译,即编译器将其解释为free((void *) x) 。 在这种情况下,非常数整数值x被转换为指针类型void * 。 此转换的结果是实现定义。 注意,该语言保证当值为0的ICE转换为指针类型时,结果为空指针。 但在你的情况下, x不是ICE,因此转换的结果是实现定义的。 在C中,无法保证通过将值为0的非ICE整数转换为指针类型来获取空指针。 在你的实现上,可能恰好发生了(void *) x其中非ICE x等于0产生类型为void *的空指针值。 传递给free ,此空指针值会根据free的规范产生no-op。

但是在一般情况下,将这样的指针传递给free将导致未定义的行为。 你可以合法地传递给free的指针是先前调用malloc / calloc / realloc和null指针获得的指针。 在一般情况下,您的指针违反此约束,因此行为未定义。

这就是你的情况。 但是,您的代码再次包含约束违规。 即使您覆盖违规,行为也是未定义的。

PS注意,顺便说一句,这里已经发布的许多答案都犯了同样严重的错误。 他们假设(void *) x和零x应该产生一个空指针。 这绝对不正确。 同样,当x不是ICE时,语言绝对不能保证(void *) x的结果。 (void *) 0保证为空指针,但(void *) x与零x 保证是空指针。

这将在C FAQ http://c-faq.com/null/runtime0.html中介绍 。 对于那些有兴趣更好地理解其原因的人来说,阅读有关空指针的整个部分可能是个好主意http://c-faq.com/null/index.html

在你的情况下,它的工作原理是因为调用free(NULL)(即free(0))是一个NOOP。 但是,如果使用0以外的任何值(NULL)调用它,则行为将是未定义的 – 崩溃和/或内存损坏可能是候选者。

编辑:正如其他人后来指出的那样,free(x)(x = 0)和free(NULL)不是一回事。 (虽然它通常为0,但NULL指针的值是实现定义的,不能依赖它。)请参阅AndreyT的答案以获得非常好的说明。

释放NULL(或0)什么都不做。 这是一个无操作。

您是否尝试过编译器的警告级别? 例如gcc -ansi -pedantic -W -Wall报告:

tmp.c:6:警告:传递’free’的参数1使得整数指针没有强制转换

行为未定义。 不要这样做。

free手册页:

free()释放ptr指向的内存空间,该内存空间必须由之前调用malloc(),calloc()或realloc()返回。 否则,或者如果之前已经调用了free(ptr),则会发生未定义的行为。 如果ptr为NULL,则不执行任何操作。

在你的例子中,你实际上是在调用free(0) ,因为free接受一个指针作为参数。 你实际上是在告诉运行时释放地址0的内存,而这个内存以前没有malloc分配过。

由于’0’为NULL,所以不会发生任何事情。 (感谢评论指出我的愚蠢错误)。

free()适用于动态分配的内存,即使用malloc,calloc或realloc分配的内存。 此外,它需要一个指针,你传递的是x的值。 没有理由在堆栈分配的变量上调用它,当堆栈展开并且行为未定义时将释放它们。 总是很好阅读文档。

http://www.cplusplus.com/reference/clibrary/cstdlib/free/

它应该在大多数体系结构上抛出访问冲突。 好吧,它是0,所以它的工作原理,但如果它不是0,它将失败。 这是未定义的。 你不能free()一个堆栈分配变量。

  

 free(0);

 “使用NULL值调用自由函数,将无效。”

实际上,当我们释放使用内存时,它会产生影响。

这里x值为零,因此它不会产生任何问题。 如果x的值不是

在这种情况下,它可能会出现分段错误。 因为x值可能用作

记忆表示一些其他变量。