Почему двоичное дерево, использующее небезопасный код, имеет плохой доступ к памяти в режиме отладки, но не освобождает? - PullRequest
0 голосов
/ 22 февраля 2019

Я пытаюсь реализовать двоичное дерево в небезопасном Rust, и похоже, что это разница между отладкой и выпуском.

Этот код, выполняемый при отладке, с большой вероятностью получит доступ к неправильному адресу памяти, но если он скомпилирован врежим релиза, кажется, все в порядке.

Вполне возможно, что я допустил ошибку, так как я совсем новичок в необработанных указателях, но иметь другой вывод действительно странно.

Мой другой выводдействительно признак неправильного доступа к памяти?Это ожидается при работе с небезопасным Rust?Это какой-то признак запаха кода?

В режиме отладки на моей машине вывод:

constructing tree
5
constructed
0.000000000000000000000000000000000000000000001
value added

В режиме выпуска на моей машине вывод:

constructing tree
5
constructed
5
value added

Здесь код, уменьшенный настолько, насколько я мог.

use std::ptr;

struct Node {
    value: f32,
    node_left: *mut Node,
    node_right: *mut Node,
}

impl Node {
    pub fn from_value(value: f32) -> Node {
        println!("{}", value);
        Node {
            value: value,
            node_left: ptr::null_mut(),
            node_right: ptr::null_mut(),
        }
    }

    fn get_value(&self) -> f32 {
        self.value
    }
}

pub struct BinaryTree {
    root: *mut Node,
}

impl BinaryTree {
    pub fn from_value(value: f32) -> BinaryTree {
        let mut node = &mut Node::from_value(value);
        BinaryTree { root: node }
    }

    pub fn add(&mut self, value: f32) {
        println!("{}", unsafe { self.root.as_mut() }.unwrap().get_value());
    }
}

fn main() {
    println!("constructing tree");
    let mut x = BinaryTree::from_value(5.0f32);
    println!("constructed");
    x.add(2f32);
    println!("value added");
}

Я запустил это на Ubuntu 18.04 в виртуальной машине Oracle, используя Rust 1.32.0.

1 Ответ

0 голосов
/ 22 февраля 2019

В BinaryTree::from_value вы создаете новый Node, а затем сохраняете указатель на него.Однако Node выделяется в стеке и удаляется перед вызовом BinaryTree::add.Поскольку вы используете указатели и unsafe вместо ссылок, компилятор Rust не может предупредить вас о таких проблемах при жизни.

Относительно того, почему это не работает в режиме отладки, но работает в режиме выпуска, он можетиз-за оптимизации, которая включена только для режима выпуска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...