Search code examples
crustffi

When passing a Rust pointer to C should I get 0x1?


I'm trying to implement a basic library in Rust that creates an object and returns its pointer to C. The pointer I get doesn't look like it is on the heap — when I print it I get 0x1:

use std::fmt;

pub struct SndbDB {}

impl SndbDB {
    fn new() -> SndbDB {
        SndbDB {}
    }
}

impl fmt::Display for SndbDB {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(sndb_db)")
    }
}

// Implement a destructor just so we can see when the object is destroyed.
impl Drop for SndbDB {
    fn drop(&mut self) {
        println!("[rust] dropping {}", self);
    }
}

#[no_mangle]
pub extern "C" fn sndb_db_create() -> *mut SndbDB {
    let _db = Box::into_raw(Box::new(SndbDB::new()));
    println!("[rust] creating DB {:?}", _db);
    _db
}

#[no_mangle]
pub unsafe extern "C" fn sndb_db_destroy(ptr: *mut SndbDB) {
    println!("[rust] destroying DB {:?}", ptr);
    Box::from_raw(ptr); // Rust drops this for us.
}

The C calling code is trivial too:

typedef struct sndb_db sndb_db;

sndb_db * sndb_db_create(void);
void sndb_db_destroy(sndb_db* db);

void test_baseapi__create_and_destroy_db(void)
{
    sndb_db * db = sndb_db_create();
    printf("[C] Got db=%p\n",db);
    sndb_db_destroy(db);
    printf("[C] db should be dead by now...\n");
}

And all the output except the pointer location are as I expect:

[rust] creating DB 0x1
[C] Got db=0x1
[rust] destroying DB 0x1
[rust] dropping (sndb_db)
[C] db should be dead by now...

I know that memory allocated in Rust needs to be deallocated by Rust - but I'm still surprised it is using a location of 0x1 - am I doing something wrong, is something odd happening, or is this all OK?


Solution

  • It looks like this is an optimisation by Rust since the SndbDB struct has no state.

    Adding an i: u32 field to it and plumbing that through to the constructor functions and the C code I then get:

    [rust] creating DB 0x7fff2fe00000
    [C] Got db=0x7fff2fe00000
    [rust] destroying DB 0x7fff2fe00000
    [rust] dropping (sndb_db i=123)
    [C] db should be dead by now...
    

    However I'd still love to find an official source to back up this guess.