Освобожденный указатель ржавчины не был выделен ошибка - PullRequest
0 голосов
/ 31 января 2020

Вот ситуация, я хочу сделать некоторое преобразование данных из строки, и для удобства я преобразовал ее в указатель в середине, и теперь я хочу вернуть часть строки, но я застрял с это исключение:

foo(74363,0x10fd2fdc0) malloc: *** error for object 0x7ff65ff000d1: pointer being freed was not allocated
foo(74363,0x10fd2fdc0) malloc: *** set a breakpoint in malloc_error_break to debug

Когда я пытаюсь отладить программу, я получаю сообщение об ошибке, как показано выше. Вот мой пример кода:

fn main() {
    unsafe {
        let mut s = String::from_utf8_unchecked(vec![97, 98]);
        let p = s.as_ptr();
        let k = p.add(1);
        String::from_raw_parts(k as *mut u8, 1, 1);
    }
}

1 Ответ

4 голосов
/ 31 января 2020

Вы никогда не должны использовать функцию unsafe без понимания ее документации, 100%.

Итак, что означает String::from_raw_parts:

Безопасность

Это крайне небезопасно из-за количества не проверенных инвариантов:

  • Память на ptr должна быть предварительно выделена тем же распределителем стандартная библиотека использует с необходимым выравниванием ровно 1.
  • length должно быть меньше или равно емкости.
  • capacity должно быть правильное значение.

Нарушение этих правил может вызвать проблемы, такие как повреждение внутренних структур данных распределителя.

Владение ptr эффективно передается в строку, которая затем может освобождать, перераспределять или изменять содержимое памяти, на которое указывает указатель по желанию. Убедитесь, что больше ничего не использует указатель после вызова этой функции.

Здесь выделяются две вещи:

  • Память в ptr должна быть предварительно selected.
  • capacity должно быть правильным значением.

И это связано с тем, как в Rust работает распределение. По сути, для освобождения требуется только то самое значение (и тип) указателя, которое вернуло выделение.

Шенаниганы, такие как попытка освободить указатель, указывающий на середину выделения, с другим выравниванием или с другим размером, Не допускаются.

Кроме того, вы также пропустили:

  • Убедитесь, что ничто другое не использует указатель после вызова этой функции.

Здесь, оригинал экземпляр String все еще владеет выделением, и вы пытаетесь освободить один байт из него. Это никогда не может go хорошо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...