2015-07-18 11 views
9

Sto chiamando l'API LLVM tramite RFI's FFI. LLVMPrintModuleToStringuses strdup to create a string. Tuttavia, quando avvolgo il puntatore in un CString, viene visualizzato un errore quando Rust lo rilascia.Come liberare un carattere * assegnato tramite FFI in 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); 
} 

errore 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 

Perché è questo? Qual è il modo corretto di gestire un *char da un'API C?

+0

È possibile liberare una funzione C e chiamare la funzione C? – WiSaGaN

risposta

13

Secondo the function's documentation:

Use LLVMDisposeMessage to free the string.

Nel caso generale, se si chiama una funzione in una libreria che alloca la memoria, si dovrebbe chiamare un'altra funzione in quella biblioteca che libera la memoria; questo dovrebbe generalmente essere documentato come parte del contratto della funzione.

Se la documentazione per una funzione che si dice di usare free, allora avrai un problema se l'applicazione non è il collegamento con il free corrispondente al malloc (ad esempio il link dell'applicazione della biblioteca con msvcr120, ma i collegamenti di libreria con msvcr100). Questo è il motivo per cui le buone librerie forniscono un metodo per deallocare le risorse che esso alloca per te.

L'allocatore di memoria predefinito in Rust non è C malloc, ma un altro allocatore denominato jemalloc. CString presuppone che la stringa sia allocata con l'allocatore di memoria di Rust, quindi quando il distruttore di CString esegue, esegue jemalloc's free (lo si può dire dalle funzioni je_ -prefixed nello stack di chiamate), ma non riesce perché la stringa non è stata allocata con jemalloc's malloc.

+0

Grazie, è davvero illuminante. –

Problemi correlati