Memory management 手动内存管理

Memory management 手动内存管理,memory-management,rust,Memory Management,Rust,当我开始学习C语言时,我实现了常见的数据结构,如列表、地图和树。我使用malloc、calloc、realloc和free在请求时手动管理内存。我用C++做了同样的事情,使用新< /COD>和删除< /C> > /P> 现在生锈了。似乎锈不提供任何与C或C++对应的函数或运算符,至少在稳定版本中。 结构和模块(标有实验性)是这种东西的研究对象吗 我知道这些数据结构已经在语言中了。这是为了学习。在Rust中直接访问内存分配器是非常罕见的。您通常希望对单个对象使用智能指针构造函数(Box::new,

当我开始学习C语言时,我实现了常见的数据结构,如列表、地图和树。我使用
malloc
calloc
realloc
free
在请求时手动管理内存。我用C++做了同样的事情,使用<代码>新< /COD>和<代码>删除< /C> > /P> 现在生锈了。似乎锈不提供任何与C或C++对应的函数或运算符,至少在稳定版本中。 结构和模块(标有
实验性
)是这种东西的研究对象吗


我知道这些数据结构已经在语言中了。这是为了学习。

在Rust中直接访问内存分配器是非常罕见的。您通常希望对单个对象使用智能指针构造函数(
Box::new
Rc::new
Arc::new
),如果需要基于堆的数组,只需使用
Vec
Box

如果您真的想分配内存并获得指向它的原始指针,可以查看
Rc
的实现。(不是
Box
Box
很神奇。)为了获得它的备份内存,它实际上创建了一个
Box
,然后使用它的
进入\u raw\u non \u null
函数来取出原始指针。对于销毁,它使用分配器API,但也可以使用
Box::from_raw
然后
drop
进行销毁

结构和
ptr
模块(用实验标记)是这种东西的研究对象吗

不,作为初学者,你绝对不应该从那里开始。当你开始学习C语言时,
malloc
就是一切,它仍然是语言中极易出错的一部分——但是没有它,你无法编写任何非平凡的程序。对于C程序员来说,了解
malloc
以及如何避免所有陷阱(内存泄漏、释放后使用等)非常重要

在现代C++中,人们被教导使用智能指针来管理内存,而不是使用手工使用<代码>删除>代码>,但仍然需要调用<代码>新< /C> >为智能指针分配内存来管理。情况好多了,但仍有一些风险。而且,作为C++程序员,你需要学习<代码>新< /COD>和<代码> Debug <代码>工作,以便正确使用智能指针。 锈蚀的目的是比C或C++更安全。它的智能指针封装了所有关于如何在低级别处理内存的细节。如果您自己正在实现一个智能指针,那么您只需要知道如何分配和释放原始内存。由于所有权的管理方式,您实际上需要了解该语言的更多细节,才能编写正确的代码。这不可能像在C或C++中那样是第一课或第二课:这是一个非常高级的主题,许多Rust程序员都不需要学习


如果您想了解如何在堆上分配内存,可以从
类开始。在铁锈书中,是关于内存分配的章节。

虽然确实不建议这样做,但您可以使用
malloc
free
,就像您从C中习惯的那样。这不是很有用,但它看起来是这样的:

extern crate libc; // 0.2.65

use std::mem;

fn main() {
    unsafe {
        let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32;
        if my_num.is_null() {
            panic!("failed to allocate memory");
        }
        libc::free(my_num as *mut libc::c_void);
    }
}
extern板条箱libc;//0.2.65
使用std::mem;
fn main(){
不安全{
让my_num:*mut i32=libc::malloc(mem::size_of::()作为libc::size_t)作为*mut i32;
如果我的\u num.为\u null(){
恐慌!(“分配内存失败”);
}
libc::free(my_num as*mut libc::c_void);
}
}
更好的方法是使用Rust的标准库:

use std::alloc::{alloc, dealloc, Layout};

fn main() {
    unsafe {
        let layout = Layout::new::<u16>();
        let ptr = alloc(layout);

        *(ptr as *mut u16) = 42;
        assert_eq!(*(ptr as *mut u16), 42);

        dealloc(ptr, layout);
    }
}
使用std::alloc::{alloc,dealloc,Layout};
fn main(){
不安全{
让布局=布局::新建::();
设ptr=alloc(布局);
*(ptr as*mut u16)=42;
断言式(ptr as*mut u16),42);
解除锁定(ptr,布局);
}
}

我完全明白,智能指针是一条出路。但它们只是内部必须使用上述关键字的容器。当我评论巴斯蒂安的回答时,如果我对实现自己的内存容器感到好奇?“在现代C++中,……但是,你仍然需要调用NeXT来分配内存来管理你的智能指针。”->不。在现代C++中,人们使用和损坏。“如果我读到一本关于CPP的书,这是我首先学到的。”那本书有多老了?如果你用C++11(及更高版本)编写
new
,你就是自找麻烦
std::vector
std::make_unique
应涵盖99%的用例,
std::shared_ptr
99%的剩余用例。
new
的奇怪用法应该严格保留在基础库中实现更高级别的抽象。顺便说一句,Stroustrup在其自己的书的第171页开始讨论指针和内存管理。你为什么要这样做?首先,你要绝对确保它不能在现有的基础库中实现。在这种不太可能的情况下,您可以使用分配器API,也可以使用libc板条箱中的malloc。请注意,稳定生锈的生锈标准库可以在内部使用不稳定的功能,因此比普通代码更具特权。Doron,因为我喜欢这样做。我当然不打算在生产中使用我自己的。@LppEdd不一定应该“只在您想创建自己的智能指针时使用它”。