为何String转*const i8再转回后数据异常?Rust FFI问题
悬垂指针导致FFI字符串转换异常的问题分析
你的代码中两次字符串转换结果不一致的核心原因是悬垂指针:
循环内创建的CString实例c_item在每次迭代结束后就会被Rust的所有权机制销毁,它持有的堆内存被释放。虽然你把c_item.as_ptr()的结果存入了container,但这个指针指向的内存击倒This_dayV循环室内雅 多个 AW soundGreat,工具�,后续访问时读取到的是随机垃圾数据。
为什么第一次循环能正常输出?
第一个循环中,println语句和c_item处于同一个代码块(循环迭代的作用域),此时c_item还未被销毁,指针指向的内存仍然有效,所以能正确解析出字符串内容。
解决办法:延长CString的生命周期
要让指针始终有效,需要保证CString实例的生命周期和container一样长。可以用一个额外的向量存储所有CString实例,避免它们被提前销毁:
use std::ffi::{CStr, CString}; #[repr(C)] #[derive(Debug, Clone, Copy)] pub enum MyValue { String(*const i8), } fn main() { let content = vec!["Hello", "world"]; let mut container: Vec<MyValue> = vec![]; let mut c_strings: Vec<CString> = vec![]; // 保存CString实例,延长生命周期 // Generate data for item in content { let c_item = CString::new(item).unwrap(); c_strings.push(c_item); let c_item_ref = c_strings.last().unwrap(); container.push(MyValue::String(c_item_ref.as_ptr() as *const i8)); let my_var = *container.last().unwrap(); let MyValue::String(my_var_address) = my_var else { panic!("Error") }; let real_content = unsafe { CStr::from_ptr(my_var_address) }; println!("Before-Pointer > real_value: {:?}", real_content); } println!("===================="); // Convert vector to vector pointer let container_ptr = container.as_ptr(); // Get value for i in 0..container.len() as isize { let my_var_p = unsafe { *container_ptr.offset(i) }; let MyValue::String(my_var_address_ptr) = my_var_p else { panic!("Error") }; let real_content_ptr = unsafe { CStr::from_ptr(my_var_address_ptr) }; println!("After-Pointer > real_value: {:?}", real_content_ptr); } }
修改后,c_strings会持有所有CString实例的所有权,只要c_strings不被销毁,指针指向的内存就始终有效,两次循环都能正确输出字符串内容。
内容的提问来源于stack exchange,提问作者Jayden
相关产品推荐
相关产品推荐

