gpt4 book ai didi

c - 为什么从C调用Rust库会导致内存泄漏?

转载 作者:行者123 更新时间:2023-12-03 11:41:01 26 4
gpt4 key购买 nike

我试图证明C可以调用Rust库。它可以工作,但是当我监视程序的内存使用量时,它会越来越大。
Cargo.toml:

[lib]
name="test_ccallr"
crate-type=["cdylib"]
path = "src/lib.rs"

[dependencies]
libc = "0.2"
C代码:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

struct Payload_t{
char* data;
int len;
};

int show_str(char* raw, struct Payload_t *data);

int main()
{
while(1){
char * p_raw = "hlease print it !ello this is string from c, please print it !";
char * p_raw_ = "hhello this is another ";

char * pp = (char* )malloc(strlen(p_raw));
memcpy(pp, p_raw, strlen(p_raw));

struct Payload_t *tmp = (struct Payload_t*)malloc(sizeof (struct Payload_t));
struct Payload_t *_tmp = tmp;
tmp->data = (char*)malloc(strlen(p_raw_));
memcpy(tmp->data, p_raw_, strlen(p_raw_));
tmp->len = strlen(p_raw_);
printf("\n%d %d %d", pp, tmp, tmp->data);
show_str(pp, tmp);
printf("\n%d %d %d", pp, tmp, tmp->data);
free(pp);
free(tmp->data);
//free(_tmp);
usleep(5);
}

return 0;
}
我使用以下命令构建C代码:
gcc main.c -L ./ -Bstatic -l:libtest_ccallr.so -o test[lib]
rust 代码:
//use std::os::raw::{c_char, c_int};
extern crate libc;
use libc::{c_char, c_int};
use std::error::Error;
use std::ffi::CStr;

#[repr(C)]
pub struct Payload_t {
data: *const u8,
len: c_int,
}

#[no_mangle]
pub extern "C" fn show_str(raw: *const c_char, data: *const Payload_t) -> i32 {
let c_str: &CStr = unsafe { CStr::from_ptr(raw) };
if let Err(err) = c_str.to_str() {
eprintln!("{}", err.description());
return 0;
}
let str_from_ptr = c_str.to_str().unwrap();

let payload_ptr: Payload_t = unsafe { *Box::from_raw(data as *mut Payload_t) };

let payload = unsafe { std::slice::from_raw_parts(payload_ptr.data, payload_ptr.len as usize) };

println!("the raw string is {}", str_from_ptr);
println!(
"the length string is {}",
std::str::from_utf8(payload).unwrap()
);

return 0;
}
如果我取消注释 //free(_tmp);,该程序将崩溃。如果我保留这一行的注释,并运行该程序,它可以运行,但是会泄漏内存。
有什么不适当的吗?

最佳答案

这是Box::from_raw不当用法:

let payload_ptr: Payload_t = unsafe { *Box::from_raw(data as *mut Payload_t) };
在文档中,重点是我的( ,请阅读文档中有关不安全功能的信息):

After calling this function, the raw pointer is owned by the resulting Box. Specifically, the Box destructor will call the destructor of T and free the allocated memory. For this to be safe, the memory must have been allocated in accordance with the memory layout used by Box.


您仅应将此函数用于要重新获得所有权的 Box::new分配的数据。你的情况都不是。 Box正在取消分配C分配的内存。这很可能是导致您对 free的调用崩溃的原因,因为Rust用自己的析构函数在内存上进行了涂抹。
编写Rust函数的一种更好的方法是不尝试获取 data的所有权:
#[no_mangle]
pub unsafe extern "C" fn show_str(raw: *const c_char, data: *const Payload_t) -> i32 {
let c_str = CStr::from_ptr(raw);
let str_from_ptr = match c_str.to_str() {
Ok(s) => s,
Err(err) => {
eprintln!("{}", err);
return 0;
}
};

let payload_ptr = &*data;
let payload = std::slice::from_raw_parts(payload_ptr.data, payload_ptr.len as usize);
let s = match std::str::from_utf8(payload) {
Ok(s) => s,
Err(err) => {
eprintln!("{}", err);
return 0;
}
};

println!("the raw string is {}", str_from_ptr);
println!("the length string is {}", s);

0
}

关于c - 为什么从C调用Rust库会导致内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65224090/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com