Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation for mem::forget implies that it may invalidate raw pointers to heap allocations #79320

Closed
fleabitdev opened this issue Nov 22, 2020 · 8 comments
Labels
A-docs Area: Documentation for any part of the project, including the compiler, standard library, and tools

Comments

@fleabitdev
Copy link

fleabitdev commented Nov 22, 2020

The doc comment for mem::forget currently reads:

Any resources the value manages, such as heap memory or a file handle, will linger forever in an unreachable state. However, it does not guarantee that pointers to this memory will remain valid.

The second sentence was introduced in #53503, with this rationale:

it's not obvious mem::forget does not guarantee leaking of memory: memory of stack-allocated objects and values partially moved out of Box will still be freed

In other words, it's intended to be a warning about these two footguns:

let byte = 42_u8;
let raw_ptr = &byte as *const u8;
std::mem::forget(byte);
let forty_two = unsafe { *raw_ptr };

let raw_ptr;
{
    let boxed_byte = Box::new(42u8);
    raw_ptr = &*boxed_byte as *const u8;
    std::mem::forget(*boxed_byte);
}
let forty_two = unsafe { *raw_ptr };

To me, the current language is too broad. It implies that heap allocations owned by a value passed to mem::forget may be invalidated. For example, it implies that the following code is unsound:

let s = format!("example");
let s_ptr = s.as_ptr();
std::mem::forget(s);
let lowercase_e = unsafe { *s_ptr };

Opening an issue rather than a PR because I'm not sure how best to rephrase this.

@jyn514 jyn514 added the A-docs Area: Documentation for any part of the project, including the compiler, standard library, and tools label Nov 22, 2020
@pierwill
Copy link
Member

pierwill commented Dec 3, 2020

Would like to work on this! ✋

@rustbot claim

@pierwill
Copy link
Member

pierwill commented Dec 3, 2020

So what can we say for sure? Maybe, based on @fleabitdev's comment: "Heap allocations owned by a value passed to mem::forget are not immediately invalidated." If it is true that mem::forget "does not guarantee that pointers to this memory will remain valid" (which seems right to me 🤷‍♀️), when might pointers to such forgotten memory in fact be invalidated? Is this unknown because undefined?

Perhaps simply adding the sentence above would help? ("Heap allocations owned by a value passed to mem::forget are not immediately invalidated.")

@pierwill
Copy link
Member

pierwill commented Dec 3, 2020

Thoughts, @jyn514? Just trying to wrap my head around this.

@jyn514
Copy link
Member

jyn514 commented Dec 3, 2020

@pierwill sorry, I don't even understand why the original example is incorrect, I can't guess why the third example is sound.

@fleabitdev
Copy link
Author

fleabitdev commented Dec 3, 2020

When a value is passed to mem::forget, safe Rust code will never run its destructor, and so any heap allocations owned by the value will live forever (unsafe code notwithstanding). This is the point which I feel is obscured by the current documentation.

It's an important property of mem::forget; I've written unsafe code which relies on it. You can insert checks in a type's destructor to prevent memory from being deallocated when it's unsafe to do so, but if mem::forget could implicitly perform deallocations, those checks would be bypassed.

@steveklabnik
Copy link
Member

cc @rust-lang/lang @rust-lang/libs

@pierwill
Copy link
Member

@rustbot release-assignment

@pnkfelix
Copy link
Member

pnkfelix commented Mar 7, 2022

I think this is best handled by delegating to the unsafe-code-guidelines WG. (That is, I think any of the footguns and issues discussed arised solely in the context of unsafe code. All sound code should continue to be sound.)

Filed rust-lang/unsafe-code-guidelines#320 and closing this.

@pnkfelix pnkfelix closed this as completed Mar 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-docs Area: Documentation for any part of the project, including the compiler, standard library, and tools
Projects
None yet
Development

No branches or pull requests

5 participants