2015-07-18 2 views
9

Ich rufe die LLVM API über Rust FFI. LLVMPrintModuleToStringuses strdup to create a string. Jedoch, wenn ich den Zeiger in eine CString wrap, bekomme ich einen Fehler, wenn Rust es fallen lässt.Wie kann ich ein * Char über FFI in Rust freigeben?

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

==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 

Warum ist das? Was ist der richtige Weg, um eine *char von einer C-API zu behandeln?

+0

Haben Sie eine C-Funktion frei, und rufen Sie diese C-Funktion? – WiSaGaN

Antwort

13

Nach the function's documentation:

Use LLVMDisposeMessage to free the string.

Im allgemeinen Fall, wenn Sie eine Funktion in einer Bibliothek aufrufen, die Speicher zuweist, können Sie eine andere Funktion in der Bibliothek aufrufen sollte, die den Speicher freigibt; Dies sollte im Allgemeinen als Teil des Vertrags der Funktion dokumentiert werden.

Wenn die Dokumentation für eine Funktion sagt Ihnen free zu nutzen, müssen Sie dann ein Problem, wenn Ihre Anwendung mit dem free entsprechend der Bibliothek malloc (zB Ihre Anwendung Verbindungen mit msvcr120, aber die Bibliothek Links nicht mit Verlinkung msvcr100). Aus diesem Grund bieten gute Bibliotheken eine Methode zum Zuweisen von Ressourcen, die für Sie zugewiesen werden.

Der Standard-Speicherzuordner in Rust ist nicht C malloc, sondern ein anderer Zuweiser namens jemalloc. CString nimmt an, dass die Zeichenfolge mit Rust Speicherzuordner zugewiesen wurde, so wenn CString Destruktor ausgeführt wird, es free von jemalloc ausgeführt wird (Sie können aus den je_ -vorfixed Funktionen in Ihrem Aufruf-Stack), aber es schlägt fehl, weil die Zeichenfolge nicht zugeordnet wurde jemallocs malloc.

+0

Danke, das ist wirklich erhellend. –

Verwandte Themen