C 到 Rust 并返回“未分配被释放的指针"在锈侧 [英] C to Rust and back "pointer being freed was not allocated" on Rust side
问题描述
我正在尝试从 C 调用一些 Rust 代码并返回结果,但是我在 Rust 端收到一个被释放的指针未分配"错误.
I'm trying to call some Rust code from C and get a result back, but I'm getting a "pointer being freed was not allocated" error on the Rust side.
我想调用 hex::encode
函数.我传入了一个指向某些字节的指针、长度和一个在 C 中使用 malloc 分配的指针.我想要在这个指针处传回转换的结果.
I want to call the hex::encode
function. I pass in a pointer to some bytes, the length, and a pointer allocated in C with malloc. I want the result of the conversion passed back at this pointer.
Rust 函数:
extern crate libc;
use hex;
use std::ffi::CString;
use std::os::raw::c_char;
use std::vec::Vec;
use std::{ffi, ptr, slice};
#[no_mangle]
pub extern "C" fn bytes_to_hex_string(bp: *mut u8, bp_size: usize, sp: *mut c_char) -> i8 {
println!("1");
let p_vec = unsafe { Vec::from_raw_parts(bp, bp_size, bp_size + 1) };
println!("2");
let str = hex::encode(p_vec);
println!("3");
let bytes = str.as_bytes();
println!("4");
let cs = CString::new(bytes).unwrap(); // will fail if bytes has "gap" (null) in sequence
println!("5");
unsafe {
libc::strcpy(sp, cs.as_ptr());
}
println!("6");
return 1;
}
从此C代码调用:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int8_t bytes_to_hex( uint8_t *, unsigned int, char *);
int main() {
char *ptr = "Hello World!";
char *hex = (char *)malloc(1000);
printf("about to call....\n");
bytes_to_hex_string((uint8_t*)ptr,strlen(ptr),hex);
printf("about to print....\n");
printf("%s\n",hex);
printf("about to free....\n");
free(hex);
}
当我运行程序时:
$ ./a.out
about to call....
1
2
a.out(2941,0x7fffccae03c0) malloc: *** error for object 0x10afe2b80: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
看起来 hex crate 中的 Rust 代码正在释放 ptr
指针,对吗?
It looks like the Rust code inside the hex crate is freeing the ptr
pointer, is that right?
有没有办法解决这个问题?我更喜欢在 C 中进行分配和释放,但我愿意接受任何解决此问题的建议!
Is there a way round this somehow? I would prefer for the allocation and freeing to happen in C, but I am open to any suggestions to solve this!
推荐答案
如果您不希望 Rust 释放您的指针,请不要使用拥有分配的类型.Vec
和 CString
都获得指针的所有权并对其进行管理.想必您对需要同时提供长度和容量感到惊讶吗?
If you don't want Rust to deallocate your pointer, don't use types that own the allocation. Vec
and CString
both take ownership of the pointer and manage it. Presumably you were surprised to need to provide both a length and a capacity?
使用 slice::from_raw_parts
代替:
Use slice::from_raw_parts
instead:
extern crate libc;
extern crate hex;
use std::ffi::CString;
use std::os::raw::c_char;
use std::slice;
#[no_mangle]
pub unsafe extern "C" fn bytes_to_hex_string(bp: *mut u8, bp_size: usize, sp: *mut c_char) -> i8 {
let p_vec = slice::from_raw_parts(bp, bp_size);
let str = hex::encode(p_vec);
let cs = CString::new(str).unwrap();
libc::strcpy(sp, cs.as_ptr());
return 1;
}
我没有测试过这个,所以我不能说你的 strcpy
是否正确.然而,在 FFI 函数中恐慌是未定义的行为.同样令人惊讶的是,您将两个指针都声明为可变的……您也不需要导入 Vec
,因为它在前奏中.
I didn't test this, so I cannot say if your strcpy
is correct. Panicking in a FFI function is undefined behavior, however. It's also surprising that you declare both pointers as mutable... You also don't need to import Vec
as it's in the prelude.
另见:
这篇关于C 到 Rust 并返回“未分配被释放的指针"在锈侧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!