Is there any option to use shared memory for Vec<f64> in Rust?
Processes in my program swap two or more values in a Vec<f64> and I need the memory to be shared between processes.
There is no way to safely create a Vec backed by shared memory. There are two reasons this is true:
A Vec owns its memory and will reallocate it when grown or free it when dropped. Unsafely creating a Vec pointing to mmapped memory will corrupt the heap when the Vec reallocates or goes out of scope.
A Vec has exclusive access to its memory, like a &mut reference. The compiler is free to omit and reorder reads and writes based on the assumption that nothing else is using the memory. If this assumption is broken, the behavior is undefined. To relax this assumption, your data type needs to be something based on UnsafeCell.
Vec is the wrong pointer for this job. Try &[UnsafeCell<f64>], or maybe &[AtomicU64] (with conversions using from_bits and to_bits), since there isn't an AtomicF64 in the standard library.
Related
As you know, both Box::into_raw() and Box::leak() consume the current Box and lose ownership of the memory.
The two just seem to have different types of return values, what exactly is the other difference between them?
How about typical application scenarios?
into_raw is typically used for FFI to get a pointer that can be sent to the other language, and is usually matched with a later call to from_raw to reclaim ownership and free the memory.
leak is typically used to get a 'static reference to satisfy some API requirement and is usually kept until the program exits.
According to https://doc.rust-lang.org/stable/rust-by-example/std/box.html,
All values in Rust are stack allocated by default. Values can be boxed
(allocated on the heap) by creating a Box. A box is a smart pointer
to a heap allocated value of type T. When a box goes out of scope, its
destructor is called, the inner object is destroyed, and the memory on
the heap is freed.
So if I have a std::vec::Vec<MyStruct> and I add a lot of structs, does this mean that the structs are stack allocated? How can this be possible? I can only have a collection of things if they're on the heap. Things on the stack are made in compile time, since I understand.
A Box is one way of allocating on the heap, but it is not the only way. Other data structures, including Vec, store their data on the heap. So in this case, as you create each instance of MyStruct initially it will be on the stack, but as soon as you push it onto the Vec, it will be moved to the heap. At least, that's conceptually how it works; depending on the specific situation and the compiler optimization settings, Rust may be able to avoid physically writing to the stack, instead writing directly to the heap.
When searching for an answer, I found this question, however there is no mention of static lifetime objects. Can the method mentioned in this answer (calling drop() on the object) be used for static lifetime objects?
I was imagining a situation like a linked list. You need to keep nodes of the list around for (potentially) the entire lifetime of the program, however you also may remove items from the list. It seems wasteful to leave them in memory for the entire execution of the program.
Thanks!
No. The very point of a static is that it's static: It has a fixed address in memory and can't be moved from there. As a consequence, everybody is free to have a reference to that object, because it's guaranteed to be there as long as the program is executing. That's why you only get to use a static in the form of a &'static-reference and can never claim ownership.
Besides, doing this for the purpose of memory conservation is pointless: The object is baked into the executable and mapped to memory on access. All that could happen is for the OS to relinquish the memory mapping. Yet, since the memory is never allocated from the heap in the first place, there is no saving to be had.
The only thing you could do is to replace the object using unsafe mutable access. This is both dangerous (because the compiler is free to assume that the object does not in fact change) and pointless, due to the fact that the memory can't be freed, as it's part of the executable's memory mapping.
It seems like Box.clone() copies the heap memory. As I know, Box will get destructed after it gets out of its scope, as well as the memory area it is pointing to.
So I'd like to ask a way to create more than one Box object pointing to the same memory area.
By definition, you shall not.
Box is explicitly created with the assumption that it is the sole owner of the object inside.
When multiple owners are required, you can use instead Rc and Arc, those are reference-counted owners and the object will only be dropped when the last owner is destroyed.
Note, however, that they are not without downsides:
the contained object cannot be mutated without runtime checks; if mutation is needed this requires using Cell, RefCell or some Mutex for example,
it is possible to accidentally form cycles of objects, and since Rust has no Garbage Collector such cycles will be leaked.
Basically I have a heap-allocated struct Box<State>. I have multiple Value structs that need to have an immutable reference to this heap-allocated struct.
What kind of attribute can I use inside of Value for this reference? Using Rc<Box<State>> does not work because I need Value to implement Copy and State does not implement Copy. When it needs to copy itself, I just want to copy the pointer to that heap-allocated State.
What you're asking for is basically impossible. If you have many pointers to the heap allocation floating around, you need to somehow keep track of these pointers to be able to deallocate once all these pointers are destroyed. However, that requires doing something whenever one of the pointer is duplicated, and/or doing something when the pointers are destroyed.
Well, that's not quite true, there are two ways around this:
Don't deallocate, i.e., leak memory
Have a garbage collector periodically going through all memory that might contain pointers to the allocation.
But the first is impractical in most contexts (and quite dirty even when you can afford it), and the second has other costs and far-reaching consequences and is not really well supported in current Rust anyway.
The only sane thing is to drop the Copy requirement. Perhaps you're confusing Copy with Clone? The primary difference between the two is that you have to call clone() explicitly while Copy works implicitly. Rc<anything> is Clone and cloning the reference counted pointer will only increment the refcount, not clone the thing behind the pointer. (And in this case you almost certainly can and should get rid of the Box, since Rc<T> already allocates the T on the heap, so the Box is just a pointless additional indirection.)