I'm using Rust's FFI to call LLVM. Here's a minimal working example, based on the example provided with the library.
extern crate llvm_sys as llvm;
fn main() {
unsafe {
let module = llvm::core::LLVMModuleCreateWithName(b"nop\0".as_ptr() as *const _);
llvm::core::LLVMDumpModule(module);
llvm::core::LLVMDisposeModule(module);
}
}
This works, and valgrind reports no errors. However, I want to use Rust strings in my code, so I wrote this:
extern crate llvm_sys as llvm;
use std::ffi::CString;
/// Convert a Rust string to a C char pointer.
fn cstr(s: &str) -> *const i8 {
let cstring = CString::new(s).unwrap();
cstring.to_bytes_with_nul().as_ptr() as *const _
}
fn main() {
unsafe {
let module = llvm::core::LLVMModuleCreateWithName(cstr("nop"));
llvm::core::LLVMDumpModule(module);
llvm::core::LLVMDisposeModule(module);
}
}
However, valgrind now reports:
==7147== ERROR SUMMARY: 6 errors from 4 contexts (suppressed: 0 from 0)
Is this because cstring
is being dropped when cstr
returns? Since cstr
is safe, why does the compiler not complain about cstr
? What's the correct way to pass arbitrary Rust strings to C libraries?