ManuallyDrop::new ( Box::new( tree_of_prox {
ppid: pid,
up: ptr::null_mut (),
kids: _kids,
proxid_of_kid: __proxid_of_kid,
direction_to_count: false,
cursor: 0
} ) )
this doesn't prevent Rust to touch/drop memory - it's rather confusing..
What is the question?
ManuallyDrop does not prevent something from being accessed. It only prevents it from being automatically dropped when it goes out of scope.
If this is not what you see happening, there is probably a coding error. If so, please show the specific code that is using ManuallyDrop and say why you think it is being dropped automatically.
The code you posted is using ManuallyDrop in many places. For other people to understand the problem, you may need to create a small example that shows the problem. (And while creating this you may discover the cause of the problem.)
the're two core funcs: mk_branch_of_prox & mk_root_of_prox. To reproduce..
bash > ~/Rust/TAM/target/debug/sark0y_tam_rst -find-files -path ~/Rust/Mademoiselle-Entropia/src -in-name "pass==-iE .rs" -view-w "nvim.app" -view-w "nano" -tui-app "vim"
Now press >Insert< and type: sig 2 proc >pid< -stop
I am not willing to debug your program with this small amount of information, especially with the very large amount of unsafe code you have. If you can't explain the problem clearly (perhaps using translation software if necessary), or create a small example showing the problem, then I won't be able to help you.
When looking at your code, I think you're going about this the wrong way and it should be rewritten. You're using lots of unsafe code to create a tree with self-referential structs -- this is not supported by Rust without unsafe code, and that unsafe code is extremely difficult to write correctly. Instead, use indexes or ids to refer to the nodes of your tree, instead of using pointers. This is a common way of solving this problem, and does not require unsafe code.
when You repeat steps -- the're dbg! marks. Actually, these raw pointers..
kids: *mut Vec< *mut tree_of_prox >,
proxid_of_kid: *mut Vec < i32 >,
FAILED.
this code..
let _proxid_of_kid = ManuallyDrop::new (RefCell::new( Vec::< i32 >::new() ) );
let __proxid_of_kid: *mut Vec::< i32 > = _proxid_of_kid.as_ptr();
doesn't guarantee to keep things in heap after func finishing.
unfortunately, this struct..
pub struct tree_of_prox {
ppid: i32 ,
//ppid: nix::unistd::Pid,
up: *mut tree_of_prox,
kids: *mut Vec< *mut tree_of_prox >,
proxid_of_kid: *mut Vec < i32 >,
direction_to_count: bool,
cursor: usize,
}
needs unsafe approach because that data must stay in heap beyond a scope of whatever func.
Using unsafe and raw pointers is not the solution to that problem. Instead, use use a struct with owned objects, no raw pointers, and no unsafe code.
well, how to keep data in heap??? if i would be doing all stuff within one func, it'd be a non-scalable solution.
The proximate issue is, when you write let _proxid_of_kid = /* static_vec:: < i32 > ();*/ ManuallyDrop::new ( RefCell::new( Vec::< i32 >::new() ) );
, the RefCell<Vec<i32>>
still lives on the stack, rather than the heap. So when you exit mk_root_of_prox()
, that stack space may be reused for other data, even though it was never dropped. To create a raw *mut Vec<i32>
pointer that will live for the rest of the program, you can use Box::into_raw(Box::new(Vec::<i32>::new()))
. Alternatively, to create a safe &'static mut Vec<i32>
reference that will live for the rest of the program, you can use Box::leak(Box::new(Vec::<i32>::new()))
. Alternatively, you could just have a proxid_of_kid: Vec<i32>
field directly, without the extra *mut
pointer.
stop, how RefCell can be in stack???
A RefCell<T>
directly contained in a local variable always stores its data on the stack. All that RefCell
does is add a reference counter to control how its data is accessed, mutably or immutably. You might be thinking of Rc<RefCell<T>>
, which always stores its data in a new heap allocation, to allow multiple ownership.
actually, i used Box < T > == funny-bunny, but RefCell failed even less than boxed approach. well, i 'll be digging func-as-a-var way &, if failed, will be doing customized alloc.
That's why I suggested Box::into_raw()
. If you put an item into a Box
, then immediately call Box::into_raw()
(or Box::leak()
) on that Box
, then the item will be placed on the heap, and it will never be dropped or deallocated.
let hacky_pointer: *mut tree_of_prox = self as *mut tree_of_prox;
let mut branch: mut tree_of_prox = Box::into_raw (ManuallyDrop::into_inner
/ ************************************************/ (mk_branch_of_prox( &mut *hacky_pointer ) ) );
tried
The problem is not the ManuallyDrop<Box<tree_of_prox>>
. Your tree_of_prox
is fully on the heap and will not be deallocated.
Instead, the problem is the ManuallyDrop::new(RefCell::new(Vec::new()))
for the *mut Vec<_>
pointers. It occurs in both mk_root_of_prox()
and static_vec()
. All of the RefCell
versions should be replaced with Box::into_raw(Box::new(Vec::new()))
.
Thx for Your help
this variant runs quite fine...
pub fn static_vec () -> mut Vec < T > {
/++++/ let mut this_vec = ManuallyDrop::new( Box::new (Vec:: < T >::new() ) );
/++++/ unsafe { (this_vec).set_len( 0 ); }
/++++/ let pointer: *mut Vec < T > = &mut *(*this_vec);
/*****/
pointer
}
Types like Vec and String allocate their contents on the heap. When a function returns a Vec or String, or a struct containing a Vec or String, the value is "moved" to the caller and can be assigned to a variable in the caller.
The same thing happens if the Vec or String is assigned to a different variable or a struct field in a single function. When moving such a value, only the small struct containing the heap pointer is copied -- the data on the heap is not dropped and is not copied. (If you do want to copy the data on the heap, call clone
.)
I strongly suggest reading the following. The example shows how String ownership works, and it applies equally to other objects like Vec that own heap allocated data.
https://doc.rust-lang.org/book/ch04-01-what-is-ownership.html
Using raw pointers for basic functionality like this is unnecessary. Raw pointers are only needed for advanced cases. And using raw pointers requires thoroughly understanding the nomicon. Writing unsafe code in Rust (that works without undefined behavior) is much more difficult than writing C/C++ code that uses pointers.
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.