c++ - 可以通过 C++ 访问堆栈分配的 Rust 缓冲区吗?

标签 c++ rust

为了避免头部分配,并且由于我知道以太网数据包的最大 MTU,我创建了一个小的 buffer: [u8, MAX_BYTES_TRANSPORT]在 Rust 中,C++ 应该为我填充:

pub fn receive(&mut self, f: &dyn Fn(&[u8])) -> std::result::Result<(), &str> {
    let mut buffer: [u8; MAX_BYTES_TRANSPORT] = [0; MAX_BYTES_TRANSPORT];
    //number of bytes written in buffer in the C++ side
    let written_size: *mut size_t = std::ptr::null_mut::<size_t>();
    let r = unsafe{openvpn_client_receive_just(
        buffer.as_mut_ptr(), buffer.len(), written_size, self.openvpn_client)};
所以,函数 openvpn_client_receive_just ,这是一个带有 C 接口(interface)的 C++ 函数,应该写入这个缓冲区。这安全吗?我找不到有关 C++ 中使用的堆栈分配的 Rust 缓冲区的信息
这是功能:
uint8_t openvpn_client_receive_just(
    uint8_t *buffer, size_t buffer_size, size_t *written_size, OpenVPNSocket *client)

最佳答案

Can a stack allocated buffer be accessed through C++?


.
从类型系统的角度来看,静态分配、堆栈分配或堆分配之间没有区别:C 签名只接受指针和大小,并不关心指针指向的位置。

Is this safe?


最有可能 .
只要正确编写 C 函数并遵守缓冲区的边界,这将是安全的。如果没有,那是一个错误。
有人可能会争辩说,最好有一个堆分配的缓冲区,但老实说,一旦开始写入越界,覆盖任意堆栈字节或覆盖任意堆字节都是不好的,并且具有未定义的行为。
为了额外的安全性,您可以使用嵌套在 2 个保护页面之间的堆分配。使用特定于操作系统的工具,您可以分配 3 个连续的操作系统页面(在 x86 上通常每个 4KB),然后将第一个和最后一个标记为只读并将缓冲区放在中间。然后,操作系统将捕获缓冲区之前或之后的任何(关闭)写入。但是,更大的跳跃不会……所以要减轻负担就需要付出很多努力。

Is your code safe?


您很可能需要知道写入了多少字节,因此使用空指针很奇怪。
我希望看到:
let mut written: size_t = 0;
let written_size = &mut written as *mut _;
是的,这又是一个指向堆栈变量的指针,就像在 C 中一样。

关于风格的说明。您的 Rust 代码不寻常,因为您使用完全类型化的变量和完整路径,更惯用的风格是:
// Result is implicitly in scope.

pub fn receive(&mut self, f: &dyn Fn(&[u8])) -> Result<(), &str) {
    let mut buffer = [0u8; MAX_BYTES_TRANSPORT];

    let mut written: size_t = 0;
    let written_size = &mut written as *mut _;

    //  Safety:
    //  <enumerate preconditions to safely call the function here, and why they are met>
    let result = unsafe {
        openvpn_client_receive_just(
            buffer.as_mut_ptr(), buffer.len(), written_size, self.openvpn_client)
    };

    translate_openvpn_error(result)?;

    let buffer = &buffer[0..written];
    f(buffer);

    Ok(())
}
我确实注释了 written 的类型, 以帮助推理,但严格来说,它不应该是必要的。
此外,我喜欢在我所做的每一个不安全的调用前加上使其安全的先决条件列表,以及满足它们的每个原因。它可以帮助我稍后审核我的不安全代码。

关于c++ - 可以通过 C++ 访问堆栈分配的 Rust 缓冲区吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66503106/

相关文章:

generics - 受另一个参数限制的通用参数

java - JNI添加jar库的问题

C++ - 通过网络发送 "Email Attachments"

c++ - 确定两个路径是否引用 Windows 中同一文件的最佳方法?

rust - rust :Vec <Vec <T >>到Vec <T>

rust - 使用 Rust 数据修改 C 函数中的内容会产生未知值

python - 解析和搜索字符串的更好方法?

C++ Gmock - 使用 shared_ptr <FactoryClass> 的测试函数

c++ - 调用空字符串的 c_str

rust - 如何在Rust中重载分配操作?