Изменение содержимого в функции C с данными Rust приводит к неизвестным значениям

avatar
pearzl
8 апреля 2018 в 12:27
63
1
0

Я пытаюсь вызвать функцию C в Rust и столкнулся со странной проблемой. Этот код воспроизводит мою проблему:

С

int t(uint8_t *data){
    *data = 1;
    *(data+1) = 2;
    *(data+2) = 3;
}
// block1
unsafe {
    let data = Vec::with_capacity(1024).as_mut_ptr();
    t(data);
    println!("{:?}", Vec::from_raw_parts(data, 4, 4));
}

// block2
unsafe {
    let mut data: Vec<u8> = Vec::with_capacity(1024);
    let pdata = data.as_mut_ptr();
    t(pdata);
    println!("{:?}", Vec::from_raw_parts(pdata, 4, 4));
}

Я ожидаю, что вывод будет [1, 2, 3, 0].

Только "блок2" работает, "блок1" выводит [91, 57, 49, 44]. Я понятия не имею, откуда это взялось.

Больше всего сбивает с толку то, что когда я ставлю "блок1" после "блок2" и запускаю их вместе, они оба выводят [1, 2, 3, 0] правильно.

Что я не заметил? В чем разница между двумя блоками?

Источник
attdona
8 апреля 2018 в 16:57
0

Я не могу воспроизвести вашу проблему (у меня это работает). Могу я спросить, как вы определили FFI для t()?

pearzl
8 апреля 2018 в 17:09
0

@attdona extern { fn t(data: libc::uint8_t);}, и я использую build.rs, чтобы скомпилировать его в статическую библиотеку.

attdona
8 апреля 2018 в 19:56
0

Попробуйте extern "C" { fn t(data: *mut u8); }

Ответы (1)

avatar
Steve Klabnik
8 апреля 2018 в 13:24
1

Я верю что здесь происходит

let data = Vec::with_capacity(1024).as_mut_ptr();

Это приводит к неопределенному поведению. Здесь Vec<T> является временным, поэтому память будет освобождена после выполнения этой строки, поэтому вы передаете неверный указатель на C.

.

То, что вы получаете разные результаты при перемещении кода, также, по-видимому, означает, что здесь есть UB.

pearzl
8 апреля 2018 в 17:19
0

Спасибо, это понятно. Но у меня все еще есть вопрос. Я нашел некоторые подробности в Интернете о временной вещи, и я нашел это: временная переменная. Похоже, такая же проблема, как и у меня, почему мой компилятор не выдал никакого сообщения об ошибке? мой rustc: ·rustc 1.23.0 (766bd11c8 2018-01-01)·

Steve Klabnik
8 апреля 2018 в 17:20
0

Потому что это ссылка, но здесь у вас необработанный указатель. Именно поэтому делать это небезопасно!