gpt4 book ai didi

rust - 为什么 Box 指针传递给 C 并返回给 Rust 段错误?

转载 作者:行者123 更新时间:2023-11-29 07:49:21 25 4
gpt4 key购买 nike

一些 C 代码调用下面的 Rust open 调用,它返回一个指针。稍后,C 代码将完全相同的指针传递回 close 函数,该函数试图删除(释放)它。它在 free(3) 中出现段错误。为什么?

use std::os::raw::{c_int, c_void};

struct Handle;

extern "C" fn open(_readonly: c_int) -> *mut c_void {
let h = Handle;
let h = Box::new(h);
return Box::into_raw(h) as *mut c_void;
}

extern "C" fn close(h: *mut c_void) {
let h = unsafe { Box::from_raw(h) };
// XXX This segfaults - why?
drop(h);
}

最佳答案

close ,你最终创建了一个 Box<c_void>而不是 Box<Handle>因为你没有投 *mut c_void返回*mut Handle在调用之前 Box::from_raw .

fn close(h: *mut c_void) {
let h = unsafe { Box::from_raw(h as *mut Handle) };
drop(h);
}

顺便说一下,Box实际上并没有为零大小的类型分配任何内存(例如此处的 Handle),而是使用固定的非零指针值(在当前实现中,它是类型的对齐;零 - sized 类型的对齐方式默认为 1)。装箱的零大小类型的析构函数知道不会尝试在这个虚构的内存地址处释放内存,但是 c_void不是零大小类型(它的大小为 1),因此 Box<c_void> 的析构函数尝试在地址 0x1 释放内存,这会导致段错误。

如果Handle不是零大小,那么代码可能不会崩溃,但它仍然会运行错误的析构函数(它会运行 c_void 的析构函数,它什么都不做),这可能会导致内存泄漏。析构函数运行 Drop::drop对于该类型(如果存在),则删除该类型的字段。

关于rust - 为什么 Box 指针传递给 C 并返回给 Rust 段错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54590338/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com