C на Rust и обратно "указатель на освобождение не был выделен" на стороне Rust - PullRequest
0 голосов
/ 04 октября 2018

Я пытаюсь вызвать некоторый код Rust из C и получить результат обратно, но я получаю ошибку «Указатель освобожден не был выделен» на стороне Rust.

Я хочу вызвать функцию hex::encode.Я передаю указатель на некоторые байты, длину и указатель, выделенный в C с помощью malloc.Я хочу, чтобы результат преобразования был передан обратно по этому указателю.

Функция 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

Похоже, что код Rust внутри шестнадцатеричного ящика освобождает указатель ptr, верно?

Есть ли способ как-то обойти это?Я бы предпочел, чтобы распределение и освобождение происходили в C, но я открыт для любых предложений, чтобы решить эту проблему!

1 Ответ

0 голосов
/ 04 октября 2018

Если вы не хотите, чтобы Rust освободил указатель, не используйте типы, которым принадлежит выделение.Vec и CString оба получают указатель и управляют им.Предположительно, вы были удивлены необходимостью указать длину и емкость?

Используйте вместо slice::from_raw_parts:

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, как в прелюдии.

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...