free(p);
This turns the contents of p into an invalid pointer value.
int *q = (int *)malloc(sizeof(int));
This line is not related to p .
if (p == q) {
This is implementation-defined behavior because p has an invalid pointer value.
*p = 10;
And finally, this behavior is undefined for the same reason as above.
C ++ Standard ยง3.7.4.2 / 4:
If the argument assigned to the maladaptation function in the standard library is a pointer that is not a null pointer value (4.10), the release function frees up the storage location that the pointer refers to, rendering is invalid for all pointers that reference any part of the freed storage. Direction using an invalid pointer value and passing an invalid pointer value to the release function undefined behavior . Any other use of an invalid pointer value has a behavior defined by the implementation.
Therefore, the answers to your questions:
Is it possible that execution will always be part of the if statement?
It depends on the implementation. C ++ does not guarantee it.
Why does no-optimization have an output of 14, and -O3 has an output of 10 for the same instructions?
Because undefined behavior occurs when dereferencing an invalid pointer.
In C, comparison itself is undefined behavior. Appendix J.2 in the C standard lists circumstances in which the behavior is undefined, and this list includes:
The value of the pointer to the object whose lifetime has expired is used.
You can find the following question, including all comments and answers: Undefined, undefined and implementation-specific behavior