-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
relax Rc restrictions and add strong/weak reference counted pointer type #10926
Conversation
I'd like to understand the motivation here better. It looks to me like |
@brson: If you want to have a tree with parent pointers without any struct Node {
children: ~[Rc<Node>],
parent: Rc<Node>
} However, now there's a cycle between the parent and each child, so the entire data structure will leak. These types allow you to do the following instead: struct Node {
children: ~[Strong<Node>],
parent: Weak<Node>
} The This works for any case where ownership is a directed, acyclic graph. The We could add this functionality to Rc instead, but adding an extra word to the allocation and a branch to the destructor is a undesirable. I'm not sure if it's worth paying that price for simplicity at the moment because having super lightweight reference counting is quite nice and the vast majority of use cases won't need weak references. |
👍 |
Any news on this? The ability to create cyclic references without leaks, unsafe code or non-deterministic destruction seems like an obvious thing to provide in the standard library. |
I find this compelling but I would like to discuss with the team at the next meeting. |
If I understand correctly the Strong/Weak pointers don't provide any static guarantees - you still have to structure your code correctly to avoid the cycle. So this patch would leave us with no rc types that avoid cycles statically and two slightly different ones that allow cycles. I'm not sure this is the right balance, nor that we want to provide an abundance of smart pointer types by default - can we not come up with a single refcounted type that works well enough for standard and leave more special cases to the multiverse (extra)? |
It's on the agenda for the next meeting, but that's not until 1/7. Maybe we can resolve this earlier. |
@brson: The |
We could possibly keep the size down by making the ref counts smaller, make them both u32 possibly. I'm worried about how difficult it will be to correctly structure programs using Strong/Weak pointers to avoid cycles. If we made Strong a unique type and only allowed weak pointers it would be impossible to create strong cycles. |
@brson: If |
By the way, I don't really think using |
Why check for overflow with u32? It will only overflow when you have over 4294967295 objects referring to the same object, which is not even possible on a 32-bit system, and on a 64-bit system would require 32GB worth of pointers (pointer size = 8 bytes, need 2 ^ 32 pointers) (all of which would refer to the same object!). The risk of reference count overflow seems entirely acceptable to me, unless I'm missing something important? |
@Thiez: You're missing that overflow causes memory unsafety. It's not acceptable for memory safety to be compromised... |
Except that the case where memory unsafety occurs requires a program that uses over 32GB of RAM, and that is when it does absolutely nothing but attempt to create a far-fetched scenario and has no allocation overhead. If we assume those 4.3 billion object conspiring to make the refcount overflow also contain some useful data suddenly we need over 64GB just to have a chance of this scenario to occur. Perhaps use u32 for refcounts in the rust "desktop and embedded device edition" and u64 in the "enterprise server edition"? 😉 |
An infinite loop or infinite recursion is not a far-fetched scenario and is a perfectly viable way to exploit a Rust application. If you want to use |
u32 for refcounts is sufficient |
@liigo: It's not sufficient because it breaks memory safety on overflow. |
I don't see how u32's require overflow checks but uintptr's don't. |
Each pointer takes up at least one byte, so if you had enough clones of an Rc's to overflow a uintptr, you'd've filled up your entire addressable memory (and more) with them. |
@brson one cannot overflow a uint without filling the entire address space On Mon, Jan 6, 2014 at 9:09 PM, Brian Anderson notifications@git.luolix.topwrote:
|
That is, the overflow check is a catastrophic failure. On Mon, Jan 6, 2014 at 9:13 PM, Corey Richardson corey@octayn.net wrote:
|
In the meeting today we decided to get rid of the current |
Thanks @strcat |
I canceled this build because I don't believe that the change to introduce and require a If this is a pre-emptive fix for a future GC, then I do not think it should be added at this time. If this is a soundness requirement for the current GC, I'm curious for a code example which breaks in today's GC. |
Also, would you mind rebasing the last few commits together? |
I would prefer leaving off the |
Thanks for looking into whether |
No description provided.