2017-11-25 5 views
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입니까?

답변

6

SndbDB 구조체에 상태가 없으므로 Rust가 최적화 한 것처럼 보입니다.

[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... 

을 나는 아직도이 추측을 백업하는 공식 소스를 찾을 싶어요 그러나 :

를 통해 생성자 함수와 C 코드에 그때 내려면 i: u32 그것에 필드와 배관을 추가.

+3

녹이기 때문에 실제 크기가 0 인 메모리는 메모리를 할당하지 않습니다. 대신 "자리 표시 자"포인터 값을 사용합니다. 그것은 여기서 일어나는 일입니다. 'Vec'과 비슷한 점이 있습니다 : 크기가 0 인 벡터를 가지고 있다면, 메모리를 할당하는 데 신경 쓰지 않고 푸시 한 요소의 수를 추적 할 수 있습니다. –

+0

@DK 그것이 내가 추측하고 있었던 것이었다 (비록 많은 머리카락을 뽑았지만). 이 문제를 뒷받침 할 공식 문서 나 기타 출처가 있습니까? ("소스"에 대한 참조조차도 훌륭합니다). C 및 C++은 개발자가 이러한 객체를 구별 할 수 있기를 원하므로이 작업을 피하십시오. –

+3

구현 세부 사항 때문에 어디에도 문서화되어 있지 않다고 생각합니다. ['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에 대해 메모리 할당자를 사용하면 오버 헤드가 발생하기 때문에 꽤 잘립니다. –

관련 문제