如何释放在Rust中通过FFI分配的* char? [英] How do I free a *char allocated via FFI in Rust?

查看:249
本文介绍了如何释放在Rust中通过FFI分配的* char?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过Rust的FFI调用LLVM API. LLVMPrintModuleToString 使用strdup创建字符串.但是,当我将指针包装在CString中时,Rust丢弃它时会出现错误.

I'm calling the LLVM API via Rust's FFI. LLVMPrintModuleToString uses strdup to create a string. However, when I wrap the pointer in a CString, I get an error when Rust drops it.

#![feature(cstr_memory)]
use std::ffi::CString;

extern crate llvm_sys as llvm;

fn main() {
    let llvm_ir_cstring;
    unsafe {
        let module = llvm::core::LLVMModuleCreateWithName(b"nop\0".as_ptr() as *const _);
        let llvm_ir_char_ptr = llvm::core::LLVMPrintModuleToString(module);
        llvm::core::LLVMDisposeModule(module);
        llvm_ir_cstring = CString::from_ptr(llvm_ir_char_ptr);
    }

    println!("llvm_ir_cstring: {:?}", llvm_ir_cstring);
}

Valgrind错误:

Valgrind error:

==10413== Invalid read of size 4
==10413==    at 0x4870586: pthread_mutex_lock (in /usr/lib/libpthread-2.21.so)
==10413==    by 0x17F89B: je_arena_dalloc_small (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==    by 0x178C30: je_sdallocx (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==    by 0x10FA57: heap::imp::deallocate::h1fb92d59333c497bkja (heap.rs:268)
==10413==    by 0x10F999: heap::deallocate::h5680e3fedc9e96320da (heap.rs:89)
==10413==    by 0x10F929: heap::exchange_free::h452463f962f7ec23kfa (heap.rs:131)
==10413==    by 0x10F8C5: Box$LT$$u5b$u8$u5d$$GT$::drop.1769::haf7017472635c7cf (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==    by 0x10F836: std..ffi..c_str..CString::drop.1766::h04d2b3db8d468f0c (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==    by 0x10F5FF: main::h04b7feb343e229ccgaa (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==    by 0x16DBCA: rt::unwind::try::try_fn::h2403085009213705177 (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==    by 0x16FF5A: rust_try_inner (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==    by 0x16FF33: rust_try (in /home/wilfred/projects/bfc/target/debug/bfc)
==10413==  Address 0x1d684 is not stack'd, malloc'd or (recently) free'd

这是为什么?从C API处理*char的正确方法是什么?

Why is this? What's the correct way to handle a *char from a C API?

推荐答案

根据该函数的文档:

使用LLVMDisposeMessage释放字符串.

Use LLVMDisposeMessage to free the string.

在一般情况下,如果在分配内存的库中调用一个函数,则应在该库中调用另一个释放内存的函数;通常应将其记录为职能合同的一部分.

In the general case, if you call a function in a library that allocates memory, you should call another function in that library that frees the memory; this should generally be documented as part of the function's contract.

如果函数的文档告诉您使用free,那么如果您的应用程序未与库的malloc对应的free链接(例如,您的应用程序与msvcr120链接,但该库与msvcr100链接).这就是为什么好的库提供一种方法来解除分配它为您分配的资源的原因.

If the documentation for a function tells you to use free, then you'll have a problem if your application is not linking with the free corresponding to the library's malloc (e.g. your application links with msvcr120, but the library links with msvcr100). This is the reason why good libraries provide a method to deallocate resources that it allocates for you.

Rust中的默认内存分配器不是C的malloc,而是另一个名为 jemalloc 的分配器. CString假定字符串是用Rust的内存分配器分配的,所以当CString的析构函数运行时,它将运行jemalloc的free(您可以从调用堆栈中以je_前缀的函数中看出),但是失败因为未使用jemalloc的malloc分配字符串.

The default memory allocator in Rust is not C's malloc, but another allocator called jemalloc. CString assumes the string was allocated with Rust's memory allocator, so when CString's destructor runs, it runs jemalloc's free (you can tell from the je_-prefixed functions in your call stack), but it fails because the string wasn't allocated with jemalloc's malloc.

这篇关于如何释放在Rust中通过FFI分配的* char?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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