this question has answer here:
i'm trying learn rust (newbie in low level programming), , want translate tiny lv2 amplifier (audio) plugin "amp.c" (c-code) c rust. got working (here), when host terminates, valgrind says " 64 bytes in 1 blocks lost". think know why happens, don't know how fix it.
before tired of reading, here final question:
how statically allocate struct contains c string?
and here introduction:
why happens (i think): host loads library , calls lv2_descriptor()
const lv2_descriptor* lv2_descriptor() { return &descriptor; } which returns pointer statically allocated struct of type lv2_descriptor,
static const lv2_descriptor descriptor = { amp_uri, ... }; which defined as
typedef struct _lv2_descriptor { const char * uri; ... } lv2_descriptor; why statically allocated? in amp.c says:
it best define descriptors statically avoid leaking memory , non-portable shared library constructors , destructors clean properly.
however, translated lv2_descriptor() rust as:
#[no_mangle] pub extern fn lv2_descriptor(index:i32) -> *const lv2descriptor { let s = "http://example.org/eg-amp_rust"; let cstr = cstring::new(s).unwrap(); let ptr = cstr.as_ptr(); mem::forget(cstr); let mybox = box::new(lv2descriptor{amp_uri: ptr}, ...); let bxptr = &*mybox *const lv2descriptor; mem::forget(mybox); return bxptr } so it's not statically allocated , never free it, that's guess why valgrind complains?
how trying solve it? i'm trying same thing in rust c-code does, i.e. statically allocate struct (outside of lv2_descriptor()). goal compatible lv2 library, i.e "...to avoid leaking memory..." etc., says in quote, right? tried like:
static ptr1: *const u8 = (b"example.org/eg-amp_rust\n\0").as_ptr(); static ptr2: *const libc::c_char = ptr1 *const libc::c_char; static desc: lv2descriptor = lv2descriptor{amp_uri: ptr2, ...}; but not compile, there error messages like
src/lib.rs:184:26: 184:72 error: trait `core::marker::sync` not implemented type `*const u8` [e0277] src/lib.rs:184 static ptr1: *const u8 = b"http://example.org/eg-amp_rust\n\0".as_ptr(); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/lib.rs:184:26: 184:72 note: `*const u8` cannot shared between threads safely src/lib.rs:184 static ptr1: *const u8 = b"http://example.org/eg-amp_rust\n\0".as_ptr(); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ src/lib.rs:184:26: 184:72 error: static contains unimplemented expression type [e0019] src/lib.rs:184 static ptr1: *const u8 = b"http://example.org/eg-amp_rust\n\0".as_ptr(); specific problem/question:
how statically allocate struct contains c string?
the short answer is, don't now. future rust gain ability.
what can do, statically allocate struct contains null pointers, , set null pointers useful when call function. rust has static mut. requires unsafe code, not threadsafe @ , (to best of knowledge) considered code smell.
right here consider workaround fact there no way turn &[t] *const t in static.
static s: &'static [u8] = b"http://example.org/eg-amp_rust\n\0"; static mut desc: lv2descriptor = lv2descriptor { amp_uri: 0 *const libc::c_char, // ptr::null() isn't const fn (yet) }; #[no_mangle] pub extern fn lv2_descriptor(index: i32) -> *const lv2descriptor { let ptr = s.as_ptr() *const libc::c_char; unsafe { desc.amp_uri = ptr; &desc *const lv2descriptor } }
Comments
Post a Comment