我通过Rust的FFI调用LLVM API.LLVMPrintModuleToString uses strdup to create a string. 然而,当我将指针包装在CString中时,如果 rust 掉了它,我会得到一个错误.

#![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错误:

==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的正确方法是什么?

推荐答案

根据the function's documentation:

使用LLVMDisposeMessage释放字符串.

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

如果函数的文档告诉您使用free,那么如果您的应用程序没有链接到与库的malloc对应的free(例如,您的应用程序链接到msvcr120,但库链接到msvcrfree),则会出现问题.这就是为什么好的库提供了一种方法来释放它为您分配的资源.

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

Rust相关问答推荐

为什么对不可复制数据的引用的取消引用没有O权限来避免Rust中的双重释放?

有没有办法模仿对象安全克隆?

下载压缩文件

在Rust中,如果Result是Err,运行副作用(如日志(log)记录)的惯用方法是什么

字段类型为Boxed的 struct 的生存期必须超过static

避免在Collect()上进行涡鱼类型的涂抹,以产生<;Vec<;_>;,_>;

我是否可以在Ruust中修改 struct 实例上的字符串,以使其在修改后具有相同的字符串生存期?

如何将映射反序列化为具有与键匹配的字段的定制 struct 的向量?

Trait bound i8:来自u8的不满意

Rust 的多态现象.AsRef与Derf

在0..1之间将U64转换为F64

零拷贝按步骤引用一段字节

应为关联类型,找到类型参数

找不到 .has_func 或 .get_func 的 def

UnsafeCell:它如何通知 rustc Select 退出基于别名的优化?

Option<&T> 如何实现复制

在运行时在 Rust 中加载字体

在 Rust 中,为什么整数溢出有时会导致编译错误或运行时错误?

如何重写这个通用参数?

在 Rust 中组合特征的不同方法是否等效?