C 到 Rust 并返回“未分配被释放的指针"在锈侧 [英] C to Rust and back "pointer being freed was not allocated" on Rust side

查看:86
本文介绍了C 到 Rust 并返回“未分配被释放的指针"在锈侧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从 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 释放您的指针,请不要使用拥有分配的类型.VecCString 都获得指针的所有权并对其进行管理.想必您对需要同时提供长度和容量感到惊讶吗?

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆