reference - CString::new().unwrap().as_ptr() 给出空的 *const c_char

标签 reference rust ffi raw-pointer

我有一个需要 *const std::os::raw::c_char 的 C 函数,我在 Rust 中完成了以下操作:

use std::os::raw::c_char;
use std::ffi::{CString, CStr};
extern crate libc;

fn main() {
    let _test_str: *const c_char = CString::new("Hello World").unwrap().as_ptr();
    let fmt: *const c_char = CString::new("%s\n").unwrap().as_ptr();
    unsafe { libc::printf(fmt, _test_str); }

    unsafe {
        let slice = CStr::from_ptr(_test_str);
        println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
    }
}

但是,我无法打印出_test_str,上面程序的输出很简单

string buffer size without nul terminator: 0

如果我将 _test_str 传递给某个 C 函数并看到它是一个空字符串。我做错了什么?

最佳答案

您在创建指向它的指针的同一语句中创建了一个 CStringCString 被拥有但未绑定(bind)到变量,因此它仅在封闭语句中存在,导致指针无效。 documentation for as_ptr 特别警告了这一点:

For example, the following code will cause undefined behavior when ptr is used inside the unsafe block:

use std::ffi::{CString};

let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
unsafe {
    // `ptr` is dangling
    *ptr;
}

This happens because the pointer returned by as_ptr does not carry any lifetime information and the CString is deallocated immediately after the CString::new("Hello").expect("CString::new failed").as_ptr() expression is evaluated.

您可以通过引入对整个函数都有效的变量来解决这个问题,然后创建指向这些变量的指针:

fn main() {
    let owned_test = CString::new("Hello World").unwrap();
    let _test_str: *const c_char = owned_test.as_ptr();
    let owned_fmt = CString::new("%s\n").unwrap();
    let fmt: *const c_char = owned_fmt.as_ptr();

    unsafe {
        libc::printf(fmt, _test_str);
    }

    unsafe {
        let slice = CStr::from_ptr(_test_str);
        println!(
            "string buffer size without nul terminator: {}",
            slice.to_bytes().len()
        );
    }

    // owned_fmt is dropped here, making fmt invalid
    // owned_test is dropped here, making _test_str invalid
}

如果您使用原始指针,则需要格外小心,确保它们始终指向实时数据。引入变量是准确控制数据生存时间的最佳方式 - 从变量初始化到变量超出范围的那一刻,它一直存在。

关于reference - CString::new().unwrap().as_ptr() 给出空的 *const c_char,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52174925/

相关文章:

arrays - 从程序集的角度看地址运算符和数组

xml - 如何从 XML::Simple 访问嵌套数据结构中的数据?

c# - 一个类的一个属性指的是同一个类。如何管理实例

encoding - 字符编码的最佳资源

rust - 可变借用超出范围但不能重新借用

rust - 你如何在 rust 中为 'everything else' 设置默认的#[cfg] 目标?

callback - 将结构方法设置为回调

c++ - 创建一个回调结构以传递到 LuaJIT FFI

javascript - 使用 Kony Studio 出现 NoClassDefFoundError

haskell - 在reflex-dom中,如何将值从动态传递到外部javascript函数(FFI)