Reference CString::new().unwrap().as_ptr()提供空的*const c_char

Reference CString::new().unwrap().as_ptr()提供空的*const c_char,reference,rust,ffi,raw-pointer,Reference,Rust,Ffi,Raw Pointer,我有一个C函数,它需要*const std::os::raw::C_char,我在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_ch

我有一个C函数,它需要
*const std::os::raw::C_char
,我在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());
    }
}
但是,我无法打印出
\u test\u str
,并且上面程序的输出非常简单

string buffer size without nul terminator: 0

如果我将
\u test\u str
传递到某个C函数中,并看到它是一个空字符串。我做错了什么?

您在创建指向它的指针的同一语句中创建了一个
CString
CString
是自有的,但没有绑定到变量,因此它只与封闭语句一样有效,从而导致指针无效。这一点受到以下方面的特别警告:

例如,在不安全块内使用ptr时,以下代码将导致未定义的行为:

use std::ffi::{CString};

let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
unsafe {
    // `ptr` is dangling
    *ptr;
}
这是因为
as_ptr
返回的指针不携带任何生存期信息,并且
CString
CString::new(“Hello”).expect(“CString::new failed”).as_ptr()
表达式求值后立即解除分配

您可以通过引入适用于整个函数的变量来解决此问题,然后创建指向这些变量的指针:

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
}

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

您正在创建一个
CString
语句中创建指向它的指针。
CString
是自有的,但没有绑定到变量,因此它只与封闭语句一样有效,从而导致指针无效。这一点受到以下方面的特别警告:

例如,在不安全块内使用ptr时,以下代码将导致未定义的行为:

use std::ffi::{CString};

let ptr = CString::new("Hello").expect("CString::new failed").as_ptr();
unsafe {
    // `ptr` is dangling
    *ptr;
}
这是因为
as_ptr
返回的指针不携带任何生存期信息,并且
CString
CString::new(“Hello”).expect(“CString::new failed”).as_ptr()
表达式求值后立即解除分配

您可以通过引入适用于整个函数的变量来解决此问题,然后创建指向这些变量的指针:

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
}

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

如果我一直盯着页面的引入部分而不是
看,@trentcl的可能重复项没有想到会看到警告功能分段说明。我的坏,但“鲁莽”是太多了。无论如何,谢谢你指出参考资料。另外,你指出的问题要长得多,很难抓住关键点。我很抱歉没有直接链接到相关部分,但我根本不应该链接它;您有责任保证您编写的任何
不安全的
代码,这包括在取消引用之前阅读返回原始指针的函数的文档。至于被骗者,我同意,那个特别的有点冗长。实际上可能更好。但是,我只投了一个接近的票,所以我现在不能改变它。如果我一直盯着页面的介绍部分,而不是
as\u ptr
功能小节的解释,那么@trentcl的可能副本就没想到会看到警告。我的坏,但“鲁莽”是太多了。无论如何,谢谢你指出参考资料。另外,你指出的问题要长得多,很难抓住关键点。我很抱歉没有直接链接到相关部分,但我根本不应该链接它;您有责任保证您编写的任何
不安全的
代码,这包括在取消引用之前阅读返回原始指针的函数的文档。至于被骗者,我同意,那个特别的有点冗长。实际上可能更好。然而,我只投了一票,所以我现在不能改变。