int main()
{
int x = 0;
free(x);
}
This compiles and appears to be a no-op. What actually happens? is this behavior defined?
Thanks!
Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.
Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.
Lost your password? Please enter your email address. You will receive a link and will create a new password via email.
Please briefly explain why you feel this question should be reported.
Please briefly explain why you feel this answer should be reported.
Please briefly explain why you feel this user should be reported.
No, the behavior is not defined. Moreover, the code is not supposed to compile.
Firstly, the code is not supposed to compile because it contains a constraint violation. The expression you are passing as an operand to
freehasinttype. The parameter offreehasvoid *type. The only case when anintvalue can be implicitly converted tovoid *type is when theintvalue is an Integral Constant Expression (ICE) with value0. In your casexis not an ICE, meaning that it is not implicitly convertible tovoid *. The only reason your code compiles is that for historical reasons (to support legacy code) your compiler quietly overlooks the constraint violation present in thefree(x)call. I’m sure that if you elevate the level of warnings in your compiler, it will complain (at least with a warning). A pedantic compiler will immediately issue an error forfree(x)call. Try Comeau Online, for example in C89/90 mode:(Also, did you remember to include
stdlib.hbefore callingfree?)Secondly, let’s assume that the code compiles, i.e. it is interpreted by the compiler as
free((void *) x). In this case a non-constant integral valuexis converted to pointer typevoid *. The result of this conversion is implementation defined. Note, that the language guarantees that when an ICE with value of0is converted to pointer type, the result is a null pointer. But in your casexis not an ICE, so the result of the conversion is implementation-defined. In C there’s no guarantee that you will obtain a null pointer by converting a non-ICE integer with value0to pointer type. On your implementation it probably just happened that(void *) xwith non-ICExequal to0produces a null pointer value of typevoid *. This null pointer value, when passed tofree, results in a no-op, per the specification offree.In general case though, passing such a pointer to
freewill result in undefined behavior. The pointers that you can legally pass tofreeare pointers obtained by previous calls tomalloc/calloc/reallocand null pointers. Your pointer violates this constraint in general case, so the behavior is undefined.This is what happens in your case. But, again, your code contains a constraint violation. And even if you override the violation, the behavior is undefined.
P.S. Note, BTW, that many answers already posted here make the same serious mistake. They assume that
(void *) xwith zeroxis supposed to produce a null pointer. This is absolutely incorrect. Again, the language makes absolutely no guarantees about the result of(void *) xwhenxis not an ICE.(void *) 0is guaranteed to be null pointer, but(void *) xwith zeroxis not guaranteed to be null pointer.This is covered in C FAQ http://c-faq.com/null/runtime0.html . For those interested in better understanding of why it is so it might be a good idea to read the entire section on null pointers http://c-faq.com/null/index.html