Home > Blockchain >  Pointer to a self-defined struct in Rust with raw pointers
Pointer to a self-defined struct in Rust with raw pointers

Time:01-28

I am implementing some structures to be used with search algorithms. These structures are to be stored in a Linked List during the execution of a program. After struggling a bit with integrating pointers in Rust I decided to do design the structures as it follows.

The following data structures was created to store the state:

pub struct Cell {
    map: Map,
    cost: CostType,
    player: Agent
}

The following data structure was created to store the information of a cell, its parent, and its child.

struct Node {
    state: *mut cell::Cell,
    parent: *mut cell::Cell,
    childs: [*mut cell::Cell; 4],
}

Implementing the constructors (new() methods) for this data structure is being troublesome. I know I am using raw pointers instead of the smart pointers, but it is the purpose for now. There is for sure something wrong with my syntax in the declaration of the method, but cannot find many references to sort this out. The implementation of the method for creating a new instance of a Node is the following:

fn new_node() -> Node{
    Node{
        state: &cell::Cell::new_cell() as *mut cell::Cell,
        parent: &cell::Cell::new_cell() as *mut cell::Cell,
        childs: [&cell::Cell::new_cell() as *mut cell::Cell, &cell::Cell::new_cell() as *mut cell::Cell, 
              &cell::Cell::new_cell() as *mut cell::Cell, &cell::Cell::new_cell() as *mut cell::Cell]
    }
}

When I do this, the error that I obtain is the following one:

error[E0606]: casting `&node::cell::Cell` as `*mut node::cell::Cell` is invalid
   --> src/node/node.rs:15:20
   |
15 |             state: &cell::Cell::new_cell() as *mut cell::Cell,

Using ptr::null_mut::cell::Cell() solves the issue, but I would like to know if there are any ways of solving this with the pointer operators.

CodePudding user response:

You are trying to cast a shared reference into a mutable pointer, that is not allowed by default. You can do a double cast, of course,:

&cell::Cell::new_cell() as *const cell::Cell as *mut cell::Cell

But if later you use that pointer to modify the object you will invoke Undefined Behavior, as the pointer was created from a shared reference.

Besides you are getting a pointer to a temporary, assuming new_cell() is defined are returning a Cell, so the pointer is dangling as soon your expresion ends and the temporaries are destroyed. Any use of that pointer will also be Undefined Behavior.

You probably want something like this:

Box::into_raw(Box::new(Cell::new_cell()))

That is, do a dynamic allocation and convert it into a unmanaged pointer. And it already returns a properly obtained mutable pointer, so no cast is needed.

When you want to delete the cell do:

let _ = Box::from_raw(self.state);

The let _ is not actually needed but it help to document that you are intentionally discarding the returned box, that will be dropped and the cell properly disposed.

But this is Rust, not C, and you should really not be doing this, (unless you do it just for fun). An Rc<RefCell<Cell>> will get you a long way.

CodePudding user response:

&mut cell::Cell::new_cell() as *mut cell::Cell
  • Related