Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Community Proposals
Community Proposals
tag:snake search within a tag
answers:0 unanswered questions
user:xxxx search by author id
score:0.5 posts with 0.5+ score
"snake oil" exact phrase
votes:4 posts with 4+ votes
created:<1w created < 1 week ago
post_type:xxxx type of post
Search help
Notifications
Mark all as read See all your notifications »
Q&A

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.

Comments on Is it UB to read value of heap pointer after freeing?

Parent

Is it UB to read value of heap pointer after freeing?

+3
−0

I've read in a guide that "the use of indeterminate memory for anything, including apparently harmless comparison or arithmetic, can have undefined behavior if the value can be a trap representation for the type."

The included quote from C11, section 6.2.4 §2, says:

The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

The reason I'm mentioning the quote here is partially because I don't have a copy of the C standard.

Is reading the value of a pointer returned by a heap allocation function after its deallocation truly an instance of undefined behavior? (For example, debuggers may read and output the address to various I/O destinations: printer, screen, disk, network, etc.)

Consider the following program:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  void *pointer = malloc(1);
  if (pointer == NULL) return 1;
  free(pointer);
  printf("%p\n", pointer); /* Reading the address. Undefined behavior? */
  return 0;
}

Does the specification for this differ across ANSI C and other versions of ISO C?

History

1 comment thread

Very similar question here (1 comment)
Post
+3
−1

This is not a C issue, but really about dynamically allocated memory in general.

Think about it. When you allocate a chunk of dynamic memory, the heap manager finds an available memory region of the right size (or tells you it can't give you the requested memory), marks it as in-use, and returns you a pointer to it. When you release the chunk, the heap manager marks it as unused.

What happens to the memory after that is not your business. You have no guarantee that the memory hasn't been allocated by another thread, implicitly by the run-time library, or whether the address is even still valid in your address space. It could cause a memory fault if you try to read from it.

Is reading the address returned by a heap allocation function after its deallocation truly an instance of undefined behavior?

Yes! That's the point of deallocating memory. You are saying that you're done with it. That means something else is free to use it, and may have by the time you try dereferencing the pointer again. Depending on the OS, it may have been marked as invalid memory for you and trigger some kind of trap when you try to access it.

Again, think about it. How else do you expect it to work? If you still wanted to access the memory, then you wouldn't deallocate it yet. Once you do deallocate it, it's not yours anymore.

History

3 comment threads

Pointer value access vs. dereference after deallocation (8 comments)
Works for me (2 comments)
This is not relevant (1 comment)
Pointer value access vs. dereference after deallocation

I understand that dereferencing pointers to deallocated memory is undefined behavior. However, I am specifically asking about the pointer value (the address) itself. Is it undefined behavior to simply read, copy or compare the address after the memory it pointed to has been deallocated?

alx‭ wrote 25 days ago · edited 25 days ago

Yes, it is.

To be specific, the following program triggers UB:

#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
    int  *p = malloc(42);
    free(p);
    printf("%p\n", p);  // UB; use-after-free
}

Even though it doesn't access memory through the pointer.

Lundin‭ wrote 22 days ago

alx‭ No, there is nothing in the C standard claiming that this is UB. There are various corner cases regarding trap representations and uninitialized variables with automatic storage but they do not apply here.

Lundin‭ wrote 22 days ago · edited 22 days ago

Also the OP has already done what all you didn't: quoted the relevant passage in the standard, which remains the same in ISO 9899:2024 6.2.4. The other relevant part being terms in 3.23: "indeterminate representation object representation that either represents an unspecified value or is a non-value representation." Note the complete and utter lack of the term "undefined behavior" anywhere. C23 even relaxed trap representations into (3.25) "Fetching a non-value representation permits an implementation to perform a trap but is not required to".

alx‭ wrote 22 days ago

Lundin‭

Hmmm. Thanks!

So, it indeed becomes an indeterminate representation, which means it either represents an unspecified value or is a non-value representation.

If it's an unspecified value, reading it results in unspecified behavior (which means it can have any value, and if you read it twice, you may perfectly read different values, but reading it would be fine).

And as you said, fetching a non-value representation may trap, but is not required to (3.25). However, that seems to be contradicting the text it refers to (6.2.6.1p5), although I might be misinterpreting.

Certain object representations do not represent a value of the object type. If such a representation is read by an lvalue expression that does not have character type, the behavior is undefined. [...] Such a representation is called a non-value representation.

So, you could read the pointer value through an lvalue that has character type (essentially, this means you're allowed to memcpy(3) that).

alx‭ wrote 22 days ago

... But the call above is reading it through an lvalue that is a pointer, and would produce UB if and only if it is a non-value representation (which we don't know).

Lundin‭ wrote 21 days ago

alx‭x Trap == non-value representation. Reading a value which is a trap representation is undefined behavior, nobody argued about that, but reading a value which is indeterminate does not necessarily mean you are reading a trap representation. More likely you are just reading unspecified garbage, which is unspecified behavior indeed.

alx‭ wrote 21 days ago

Lundin‭

Thanks! Yeah, I was wrong in my first message. It's not so clearly UB; it could be, but it isn't necessarily.