You are creating a CString
in the same statement as creating a pointer to it. The CString
is owned but not bound to a variable so it only lives as long as the enclosing statement, causing the pointer to become invalid. This is specifically warned about by the 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.
You can fix the problem by introducing variables which will live for the entire function, and then create pointers to those variables:
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
").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
}
If you are working with raw pointers, you need to be extra careful that they are always pointing at live data. Introducing a variable is the best way to control exactly how long that data lives - it will live from the initialization of the variable to the moment the variable goes out of scope.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…