1
Rust에서 객체를 생성하고 C에 대한 포인터를 반환하는 기본 라이브러리를 구현하려고합니다. 얻은 포인터가 힙에있는 것처럼 보이지 않습니다. 인쇄 할 때 0x1
:Rust 포인터를 C에 전달할 때 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.
}
C 호출 코드는 사소한 너무 :
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");
}
그리고 포인터 위치를 제외한 모든 출력 내가 예상대로 :
[rust] creating DB 0x1
[C] Got db=0x1
[rust] destroying DB 0x1
[rust] dropping (sndb_db)
[C] db should be dead by now...
Rust에서 할당 된 메모리가 Rust에 의해 할당 해제되어야한다는 것을 알고 있습니다. 그러나 여전히 0x1
의 위치를 사용하고 있다는 것에 놀랐습니다. 제가 잘못하고 있거나, 이상한 일이 일어나고 있거나,이 모든 것이 OK입니까?
녹이기 때문에 실제 크기가 0 인 메모리는 메모리를 할당하지 않습니다. 대신 "자리 표시 자"포인터 값을 사용합니다. 그것은 여기서 일어나는 일입니다. 'Vec'과 비슷한 점이 있습니다 : 크기가 0 인 벡터를 가지고 있다면, 메모리를 할당하는 데 신경 쓰지 않고 푸시 한 요소의 수를 추적 할 수 있습니다. –
@DK 그것이 내가 추측하고 있었던 것이었다 (비록 많은 머리카락을 뽑았지만). 이 문제를 뒷받침 할 공식 문서 나 기타 출처가 있습니까? ("소스"에 대한 참조조차도 훌륭합니다). C 및 C++은 개발자가 이러한 객체를 구별 할 수 있기를 원하므로이 작업을 피하십시오. –
구현 세부 사항 때문에 어디에도 문서화되어 있지 않다고 생각합니다. ['EMPTY'] (https://github.com/rust-lang/rust/blob/b6f554b6dc972608761db93a375bcb0e89155e1d/src/liballoc/heap.rs#L231-L237)와 최근에는 ['Unique :: empty'] (https://doc.rust-lang.org/1.19.0/src/core/ptr.rs.html#1011). 고유 한 ID에 대해 메모리 할당자를 사용하면 오버 헤드가 발생하기 때문에 꽤 잘립니다. –