Here's some FFI code that gives me SQLITE_CANTOPEN (taken from rust-sqlite3). Worked fine before, and now suddenly fails with the exact same DLL - so I thought the issue must be on Rust side. Debugging into it, it seems the string buffer isn't valid memory anymore during the C call.
#[inline(always)]
pub fn str_charstar<'a>(s: &'a str) -> std_ffi::CString {
std_ffi::CString::new(s.as_bytes()).unwrap_or(std_ffi::CString::new("").unwrap())
}
pub fn in_memory() -> SqliteResult<DatabaseConnection> {
println!("in_memory");
struct InMemory;
impl Access for InMemory {
fn open(self, db: *mut *mut ffi::sqlite3) -> c_int {
let c_memory = str_charstar(":memory:").as_ptr();
let res = unsafe { ffi::sqlite3_open(c_memory, db) };
res
}
}
DatabaseConnection::new(InMemory)
}
If I change to this:
fn open(self, db: *mut *mut ffi::sqlite3) -> c_int {
// Keep CString instance in scope, call as_ptr only in unsafe block
let c_memory = str_charstar(":memory:");
let res = unsafe { ffi::sqlite3_open(c_memory.as_ptr(), db) };
res
}
it works fine...
Now my question is whether this is expected? CString::as_ptr
says
fn as_ptr(&self) -> *const c_char
Returns the inner pointer to this C string.
The returned pointer will be valid for as long as self is and points
to a contiguous region of memory terminated with a 0 byte to represent
the end of the string.
so to me this reads like the borrowing mechanism doesn't apply here and the original code has an out-of-scope problem. Am I right on this, i.e. found a bug in the crate?