Rust调用接收命令行参数的C++函数报访问错误如何解决
问题根因
你遇到的访问越界错误是参数类型不匹配导致的,核心有两处错误:
- FFI函数签名定义错误:C++函数的第二个参数是
char *argv[],等价于二级字符指针char**,你在Rust中错误定义为了一级指针*const c_char - 参数构造逻辑错误:你直接将
Vec<CString>的指针强制转为一级字符指针传递,不符合C++函数的入参要求
修复方案
1. 修正FFI函数签名
将extern块中的函数定义修改为匹配C++的参数类型:
extern "C" { pub fn print_args(args: c_int, argsv: *const *const c_char); }
2. 修正参数构造逻辑
你需要先构造一个存储所有C字符串指针的数组,再将该数组的指针传递给C++函数,同时注意保留原始CString向量的生命周期避免悬垂指针。修正后的完整main.rs代码如下:
use std::os::raw::{c_int, c_char}; use std::ffi::CString; extern "C" { pub fn print_args(args: c_int, argsv: *const *const c_char); } fn main() { // 转换命令行参数为CString向量,保留所有权防止提前释放 let args = std::env::args() .map(|arg| CString::new(arg).unwrap()) .collect::<Vec<CString>>(); // 构造二级指针数组:存储每个CString的裸指针 let args_ptr = args.iter() .map(|c_str| c_str.as_ptr()) .collect::<Vec<*const c_char>>(); let args_len: c_int = args.len() as c_int; // 传递二级指针数组的裸指针 unsafe { print_args(args_len, args_ptr.as_ptr()) }; }
错误原因解释
你之前的写法中,Vec<CString>的as_ptr()返回的是*const CString类型,你强制转为*const c_char传递给C++函数:
- C++把这个值当成
char**解析,第一次解引用拿到的是第一个CString指向的字符串地址,所以可以正常打印出第一个参数 - 遍历到第二个参数时,C++会偏移一个指针长度(64位系统为8字节)读取下一个
char*,此时读取的是第一个字符串的后续内容转成的非法地址,触发访问越界错误。
可选优化
如果要完全符合C的argv规范,可以在构造二级指针数组时末尾追加一个空指针,适配默认需要NULL结尾的C函数:
let mut args_ptr = args.iter() .map(|c_str| c_str.as_ptr()) .collect::<Vec<*const c_char>>(); args_ptr.push(std::ptr::null());
内容的提问来源于stack exchange,提问作者Mai Daly
相关产品推荐
相关产品推荐

