Перейти к основному содержимому
  1. Rust/

Низкоуровневое представление типов в памяти в Rust (Type Layout)

728 слов·4 минуты· loading · loading · · ·Rust-middle
about-rust - Эта статья часть цикла.
Статей прочитано 0/36
0%
📚 Введение и дополнительные материалы
🟢 Начальный уровень (Rust-basic)
Не прочитана
Не прочитана
Не прочитана
Не прочитана
Не прочитана
🔵 Средний уровень (Rust-middle)

Введение
#

Писать безопасный и быстрый код — это здорово, но иногда полезно понимать, как именно наши данные располагаются на физическом уровне в оперативной памяти. В Rust компилятор берет на себя управление памятью, оптимизируя размеры типов и выравнивание. В этой статье мы разберем основные понятия Type Layout в Rust.

Поведение компилятора по умолчанию
#

  • Управление памятью: Компилятор Rust автоматически рассчитывает и задает типу такие размеры (size) и выравнивание (alignment), которые гарантированно удовлетворяют техническим требованиям всех его внутренних полей на целевой архитектуре процессора.
  • Паддинг (Padding): Компилятор имеет право автоматически вставлять неявные байты заполнения (паддинг) в структуру для обеспечения корректного выравнивания данных в памяти.
  • Переупорядочивание полей: По умолчанию Rust не гарантирует сохранение порядка полей, написанного в коде. Компилятор оставляет за собой право произвольно менять порядок полей в кортежах, структурах и перечислениях для оптимизации размера и минимизации паддинга.

Давайте изучим выравнивание, размеры типов, использование атрибутов представления #[repr(...)] и работу с тегами перечислений на интерактивных слайдах ниже:

Расположение типов в памяти в Rust
Шаг 1/3
 1use std::mem::{size_of, align_of};
 2
 3#[allow(dead_code)]
 4struct Foo {
 5    a: u8,
 6    b: u32,
 7    c: u16,
 8}
 9
10fn main() {
11    println!("Размер Foo: {} байт", size_of::<Foo>());
12    println!("Выравнивание Foo: {} байт", align_of::<Foo>());
13    
14    // Если бы поля лежали в памяти строго по порядку (a, b, c):
15    // 1 байт (a) + 3 байта паддинга + 4 байта (b) + 2 байта (c) + 2 байта паддинга = 12 байт.
16    // Однако компилятор Rust переупорядочил поля в памяти (b, c, a):
17    // 4 байта (b) + 2 байта (c) + 1 байт (a) + 1 байт паддинга = 8 байт!
18}

Выравнивание и размер по умолчанию

  • Компилятор Rust автоматически вставляет байты заполнения (padding) для правильного выравнивания.
  • По умолчанию Rust свободно меняет порядок полей в памяти для минимизации размера структуры.
  • Для Foo размер уменьшается с 12 до 8 байт благодаря оптимизации переупорядочивания полей.

Детали реализации и шаги:
#

  1. Шаг 1. Выравнивание и размер по умолчанию:

    • Каждому типу данных требуется выравнивание в памяти: адрес начала данных должен быть кратен выравниванию типа (обычно степени двойки: 1, 2, 4, 8 байт).
    • Из-за этого между полями могут образовываться пустые байты — паддинг.
    • По умолчанию (представление repr(Rust)) компилятор переупорядочивает поля структуры Foo так, чтобы они занимали 8 байт вместо 12 байт, размещая сначала самые строгие по выравниванию типы.
  2. Шаг 2. Управление расположением данных с помощью атрибутов: Для явного изменения логики размещения данных в памяти и обеспечения совместимости с другими языками используются специальные атрибуты представления:

    • #[repr(C)] — отключает оптимизацию переупорядочивания полей Rust и выстраивает их строго в том порядке, в котором они объявлены (совместимо с ABI языка C).
    • #[repr(align(N))] — принудительно устанавливает минимальное выравнивание типа в памяти (например, 16 байт).
    • #[repr(transparent)] — гарантирует, что тип имеет точно такое же представление в памяти и ABI, как и его единственное некорректное поле (используется для newtype-оберток).
  3. Шаг 3. Явное тегирование перечислений (Enum Discriminants):

    • Для перечислений можно жестко фиксировать тип числового тега (дискриминанта) в памяти и присваивать явные числовые значения каждому варианту.
    • Это позволяет осуществлять безопасное приведение типов (кастинг) из перечисления в целочисленный тип с помощью ключевого слова as.

Проверь свои знания!
#

Пройдите короткий интерактивный тест, чтобы закрепить понимание расположения типов данных в памяти.

История обновлений

  • Добавил интерактивные слайды с запускаемым кодом примеров и тесты по низкоуровневому представлению типов в памяти.
Статья прочитана
Пожалуйста, оцените насколько статья была вам полезна и понятна
Цикл статей
about-rust - Эта статья часть цикла.
Статей прочитано 0/36
0%
📚 Введение и дополнительные материалы
🟢 Начальный уровень (Rust-basic)
Не прочитана
Не прочитана
Не прочитана
Не прочитана
Не прочитана
🔵 Средний уровень (Rust-middle)

Связанные статьи

Hash Map в Rust

·962 слова·5 минут· loading · loading ·Rust-basic