memory-management - Rust 分配内存布局与大小不一致
问题描述
我一定是在这里误解了一些东西,但我写了一段简单的代码来测试内存地址并得到一些奇怪的结果:
这是代码:
使用 std::alloc::{alloc, 布局};
fn main() {
let r1 : *mut i32;
let r2 : *mut i32;
let r3 : *mut i32;
let r4 : *mut u8;
let r5 : *mut i32;
unsafe {
r1 = alloc(Layout::new::<i32>()) as *mut i32;
r2 = alloc(Layout::new::<i32>()) as *mut i32;
r3 = alloc(Layout::new::<i32>()) as *mut i32;
r4 = alloc(Layout::new::<i8>());
r5 = alloc(Layout::new::<i32>()) as *mut i32;
}
println!("Raw pointer r1: {:p}", r1);
println!("Raw pointer r2: {:p}", r2);
println!("Raw pointer r3: {:p}", r3);
println!("Raw pointer r4: {:p}", r4);
println!("Raw pointer r5: {:p}", r5);
}
当我运行它时,我得到:
Raw pointer r1: 0x7fdb17402a60
Raw pointer r2: 0x7fdb17402a70
Raw pointer r3: 0x7fdb17402a80
Raw pointer r4: 0x7fdb17402a90
Raw pointer r5: 0x7fdb17402aa0
两个问题:
我看到根据文档 i32s 占用 4 个字节,那么为什么 r1 和 r2 之间的地址空间差异是 0x10 而不是 0x04?对于 r4 和 r5 之间的情况,我预计只有 1 个字节的偏移量,同样的问题。
为什么
alloc
返回的 *mut 8 足以作为指针?我们不能只用一个字节来表示 64 位虚拟内存地址,对吧?
我正在尝试学习 rust 的这些不安全方面,因为我将在一些与内核相关的项目上工作,并且有必要使用原始指针。
解决方案
这个问题不是特定于 rust 的,而是关于内存分配如何工作的问题。内存分配器需要:
考虑底层架构的对齐要求……例如,返回的指针可能希望被处理器字长整除;
存储分配空间的大小(用于解除分配)
因此考虑分配一个 32 位整数......分配器将希望分配空间来存储:
- 用于存储分配空间大小的单词;
- 32 位整数(在这种情况下需要半个字)
由于分配希望是字对齐的,下一次分配将发生在第一个字之后的两个字或 16 个字节。
至于您的第二个问题, a* mut u8
不占用单个字节,正如为其打印的给定代码所展示的值一样。
推荐阅读
- python - python - 并行写入数据的单独线程使我的代码变慢 - 但为什么呢?
- python - 在 Aplhabets 上定义轮廓
- android - 将地图转换为对象
- python - 标签编码 n 维分类值
- groovy - 在 Groovy 中循环遍历没有迭代器的对象
- android - LifecycleObserver 使用使用较新 API 的方法产生异常
- java - com.rengwuxian.materialedittext.MaterialEditText 无法转换为 android.view.ViewGroup
- batch-file - 尝试在 Windows 10 中使用 gnu awk 来拆分大型序列文件
- javascript - 如何在我的应用程序架构中确保有效的依赖关系图
- python - 在一组文件中搜索 input_from_user 词