Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
It may or may not be undefined behavior: Depending on if the ABI of the given target system has trap representations for pointers and the value we ended up now happens to be a trap representatio...
#2: Post edited
- It may or may not be undefined behavior:
- - Depending on if the ABI of the given target system has trap representations for pointers and the value we ended up now happens to be a trap representation.
- - Otherwise it is unspecified behavior and will work fine, but print garbage.
- (C23 renamed trap values "non-value representations".)
- Be aware that there is a lot of misinformation and confusion over this out on the Internet, so you must dismiss anyone who cannot give you direct quotes from the C standard. There are lots of people subjectively claiming "it is undefined behavior because I say so"...
- ---
- This is a recurring "language lawyer" question.
- Contrary to popular belief, it is ***not*** UB to read an indeterminate value, it is _unspecified behavior_. With some special exceptions, details and C standard sources are given [here](https://stackoverflow.com/questions/11962457/when-is-using-an-uninitialized-variable-undefined-behavior/40674888#40674888).
- The `pointer` variable _was_ initialized so it is not indeterminate for that reason. Thus it doesn't matter that it has automatic storage duration or if its address was taken etc. It became indeterminate after the `free` call.
- The pointer value in itself may be a trap representation for that given pointer type, in which case the program invokes undefined behavior. (Which is highly unlikely in practice since nothing happened that changed the pointer lvalue itself.)
- Otherwise, the pointer becomes an indeterminate value which is unspecified. These kind of "wobbly values" have been up for debate a couple of times in the C committee and the conclusion were pretty much that the value need not be consistent if read several times, or the compiler might give the same garbage value every time - we don't know and we can't assume anything about it.
- Unfortunately, some bad compilers chose to be so-called "low quality implementations" in this case. That is, the compiler chose to crash and break programs needlessly when it doesn't have to. Example: [clang 15 miscompiles code accessing indeterminate values](https://stackoverflow.com/questions/75533693/clang-15-miscompiles-code-accessing-indeterminate-values). From clang 15 for x86, the compiler chose to become bats*** crazy and just cut program generation halfways, giving the programmer a half program to execute with seg fault as guaranteed outcome, which is obviously useless. That compiler remains just as broken as of today.
However, the specific example of the question (which is far less nasty than the one I cooked up in the SO post) actually runs even in clang v22 x86, printing a garbage value. x86_64 does at least to my knowledge not have any trap representations for `void*` or other object pointers.
- It may or may not be undefined behavior:
- - Depending on if the ABI of the given target system has trap representations for pointers and the value we ended up now happens to be a trap representation.
- - Otherwise it is unspecified behavior and will work fine, but print garbage.
- (C23 renamed trap values "non-value representations".)
- Be aware that there is a lot of misinformation and confusion over this out on the Internet, so you must dismiss anyone who cannot give you direct quotes from the C standard. There are lots of people subjectively claiming "it is undefined behavior because I say so"...
- ---
- This is a recurring "language lawyer" question.
- Contrary to popular belief, it is ***not*** UB to read an indeterminate value, it is _unspecified behavior_. With some special exceptions, details and C standard sources are given [here](https://stackoverflow.com/questions/11962457/when-is-using-an-uninitialized-variable-undefined-behavior/40674888#40674888).
- The `pointer` variable _was_ initialized so it is not indeterminate for that reason. Thus it doesn't matter that it has automatic storage duration or if its address was taken etc. It became indeterminate after the `free` call.
- The pointer value in itself may be a trap representation for that given pointer type, in which case the program invokes undefined behavior. (Which is highly unlikely in practice since nothing happened that changed the pointer lvalue itself.)
- Otherwise, the pointer becomes an indeterminate value which is unspecified. These kind of "wobbly values" have been up for debate a couple of times in the C committee and the conclusion were pretty much that the value need not be consistent if read several times, or the compiler might give the same garbage value every time - we don't know and we can't assume anything about it.
- Unfortunately, some bad compilers chose to be so-called "low quality implementations" in this case. That is, the compiler chose to crash and break programs needlessly when it doesn't have to. Example: [clang 15 miscompiles code accessing indeterminate values](https://stackoverflow.com/questions/75533693/clang-15-miscompiles-code-accessing-indeterminate-values). From clang 15 for x86, the compiler chose to become bats*** crazy and just cut program generation halfways, giving the programmer a half program to execute with seg fault as guaranteed outcome, which is obviously useless. That compiler remains just as broken as of today.
- However, the specific example of the question (which is far less nasty than the one I cooked up in the SO post) actually runs even in clang v22 x86, printing a garbage value. x86_64 does at least to my knowledge not have any trap representations for `void*` or other object pointers.
- ---
- **EDIT**
- To clarify to everyone why accessing the _pointer variable itself_ while it is indeterminate cannot reasonably be UB, lets consider this:
- ```c
- int* p=NULL;
- {
- int var=1;
- if(something)
- p=&var;
- }
- if(p == NULL)
- ....
- ```
- After the inner scope ends, `p` might point to a variable no longer existing - the value of `p` is indeterminate. Now if this was UB, then we couldn't do the final `if(p == NULL)` check or the program might crash on that line. That's not sensible, it would break the whole language.
- Even more obvious:
- ```c
- int* p = malloc(n);
- free(p);
- p = NULL;
- ```
- If using `p` while the value is indeterminate, you wouldn't even be able to write bog standard code like the above, because the assignment involves a value computation of the left operand `p` before it is written to (C23 6.5.17.1).
- Summary: if accessing the pointer while it's value is indeterminate, that pointer variable would turn into some kind of explosive mine that might crash the program if we ever try to reuse it again. We would never be able to verify or re-use pointer variables.
#1: Initial revision
It may or may not be undefined behavior: - Depending on if the ABI of the given target system has trap representations for pointers and the value we ended up now happens to be a trap representation. - Otherwise it is unspecified behavior and will work fine, but print garbage. (C23 renamed trap values "non-value representations".) Be aware that there is a lot of misinformation and confusion over this out on the Internet, so you must dismiss anyone who cannot give you direct quotes from the C standard. There are lots of people subjectively claiming "it is undefined behavior because I say so"... --- This is a recurring "language lawyer" question. Contrary to popular belief, it is ***not*** UB to read an indeterminate value, it is _unspecified behavior_. With some special exceptions, details and C standard sources are given [here](https://stackoverflow.com/questions/11962457/when-is-using-an-uninitialized-variable-undefined-behavior/40674888#40674888). The `pointer` variable _was_ initialized so it is not indeterminate for that reason. Thus it doesn't matter that it has automatic storage duration or if its address was taken etc. It became indeterminate after the `free` call. The pointer value in itself may be a trap representation for that given pointer type, in which case the program invokes undefined behavior. (Which is highly unlikely in practice since nothing happened that changed the pointer lvalue itself.) Otherwise, the pointer becomes an indeterminate value which is unspecified. These kind of "wobbly values" have been up for debate a couple of times in the C committee and the conclusion were pretty much that the value need not be consistent if read several times, or the compiler might give the same garbage value every time - we don't know and we can't assume anything about it. Unfortunately, some bad compilers chose to be so-called "low quality implementations" in this case. That is, the compiler chose to crash and break programs needlessly when it doesn't have to. Example: [clang 15 miscompiles code accessing indeterminate values](https://stackoverflow.com/questions/75533693/clang-15-miscompiles-code-accessing-indeterminate-values). From clang 15 for x86, the compiler chose to become bats*** crazy and just cut program generation halfways, giving the programmer a half program to execute with seg fault as guaranteed outcome, which is obviously useless. That compiler remains just as broken as of today. However, the specific example of the question (which is far less nasty than the one I cooked up in the SO post) actually runs even in clang v22 x86, printing a garbage value. x86_64 does at least to my knowledge not have any trap representations for `void*` or other object pointers.
