06.5 Размещение типов в памяти

Содержание

Слайд 2

План лекции

Про модель памяти программы
Размещение в стековом кадре
Выравнивание
Связь выравниваний производного типа и

План лекции Про модель памяти программы Размещение в стековом кадре Выравнивание Связь
его элементов
Выравнивающие байты
Динамическое распределение памяти
Стандартные функции языка Си malloc, free и др.
Doug Lea’s malloc
Накладные расходы, фрагментация
Виды ошибок и address sanitizer

Слайд 3

Модель памяти программы

Модель памяти программы

Слайд 4

Модель памяти программы

Память программы

Куча

Стек вызовов потока T - 2

Стек вызовов потока T

Модель памяти программы Память программы Куча Стек вызовов потока T - 2
- 1

Стек вызовов потока 0

Цветные блоки – значения
Стрелки – «ссылки»

Слайд 5

Модель памяти программы

Языки без указателей
Java, Python, C#, Haskel, Ocaml, etc.
Работа с памятью

Модель памяти программы Языки без указателей Java, Python, C#, Haskel, Ocaml, etc.
100% автоматическая
Сборка мусора, безопасность – бесплатно
Скорость работы ▼
Расход памяти ▲
Языки с указателями
Pascal, C, C++, golang, etc.
Работа с памятью полуавтоматическая
Сами уничтожаем ненужные значения и правильно работаем с указателями
Скорость работы ▲
Расход памяти ▼

Слайд 6

Модель памяти программы

Языки без указателей
Java, Python, C#, Haskel, Ocaml, etc.
Работа с памятью

Модель памяти программы Языки без указателей Java, Python, C#, Haskel, Ocaml, etc.
100% автоматическая
Сборка мусора, безопасность – бесплатно
Скорость работы ▼
Расход памяти ▲
Языки с указателями
Pascal, C, C++, golang, etc.
Работа с памятью полуавтоматическая
Сами уничтожаем ненужные значения и правильно работаем с указателями
Скорость работы ▲
Расход памяти ▼

Слайд 7

Модель памяти программы

Языки без указателей
Java, Python, C#, Haskel, Ocaml, etc.
Работа с памятью

Модель памяти программы Языки без указателей Java, Python, C#, Haskel, Ocaml, etc.
100% автоматическая
Сборка мусора, безопасность – бесплатно
Скорость работы ▼
Расход памяти ▲
Языки с указателями
Pascal, C, C++, golang, etc.
Работа с памятью полуавтоматическая
Сами уничтожаем ненужные значения и правильно работаем с указателями
Скорость работы ▲
Расход памяти ▼

Слайд 8

Модель памяти программы

Языки без указателей
Java, Python, C#, Haskel, Ocaml, etc.
Работа с памятью

Модель памяти программы Языки без указателей Java, Python, C#, Haskel, Ocaml, etc.
100% автоматическая
Сборка мусора, безопасность – бесплатно
Скорость работы ▼
Расход памяти ▲
Языки с указателями
Pascal, C, C++, golang, etc.
Работа с памятью полуавтоматическая
Сами уничтожаем ненужные значения и правильно работаем с указателями
Скорость работы ▲
Расход памяти ▼

Слайд 9

Модель памяти программы

Языки без указателей
Java, Python, C#, Haskel, Ocaml, etc.
Работа с памятью

Модель памяти программы Языки без указателей Java, Python, C#, Haskel, Ocaml, etc.
100% автоматическая
Сборка мусора, безопасность – бесплатно
Скорость работы ▼
Расход памяти ▲
Языки с указателями
Pascal, C, C++, golang, etc.
Работа с памятью полуавтоматическая
Сами уничтожаем ненужные значения и правильно работаем с указателями
Скорость работы ▲
Расход памяти ▼

Слайд 10

Модель памяти программы

Языки без указателей
Java, Python, C#, Haskel, Ocaml, etc.
Работа с памятью

Модель памяти программы Языки без указателей Java, Python, C#, Haskel, Ocaml, etc.
100% автоматическая
Сборка мусора, безопасность – бесплатно
Скорость работы ▼
Расход памяти ▲
Языки с указателями
Pascal, C, C++, golang, etc.
Работа с памятью полуавтоматическая
Сами уничтожаем ненужные значения и правильно работаем с указателями
Скорость работы ▲
Расход памяти ▼

Слайд 11

Модель памяти программы

Языки без указателей
Java, Python, C#, Haskel, Ocaml, etc.
Работа с памятью

Модель памяти программы Языки без указателей Java, Python, C#, Haskel, Ocaml, etc.
100% автоматическая
Сборка мусора, безопасность – бесплатно
Скорость работы ▼
Расход памяти ▲
Языки с указателями
Pascal, C, C++, golang, etc.
Работа с памятью полуавтоматическая
Сами уничтожаем ненужные значения и правильно работаем с указателями
Скорость работы ▲
Расход памяти ▼

Слайд 12

Размещение данных в стековом кадре

Компилятор размещает значения переменных в стековом кадре в

Размещение данных в стековом кадре Компилятор размещает значения переменных в стековом кадре
соответствии со стандартом языка Си
Назначает переменным адреса для хранения
Генерирует код для доступа
Переменные располагаются в стековом кадре в порядке описания
Если описаны без static/extern
Возможно присутствие неиспользуемых байтов между значениями последовательно описанных переменных

Слайд 13

Размещение данных в стековом кадре

Компилятор размещает значения переменных в стековом кадре в

Размещение данных в стековом кадре Компилятор размещает значения переменных в стековом кадре
соответствии со стандартом языка Си
Назначает переменным адреса для хранения
Генерирует код для доступа
Переменные располагаются в стековом кадре в порядке описания
Если описаны без static/extern
Возможно присутствие неиспользуемых байтов между значениями последовательно описанных переменных

Слайд 14

Размещение данных в стековом кадре

Компилятор размещает значения переменных в стековом кадре в

Размещение данных в стековом кадре Компилятор размещает значения переменных в стековом кадре
соответствии со стандартом языка Си
Назначает переменным адреса для хранения
Переменные располагаются в стековом кадре в порядке описания
Если описаны без static/extern
Возможно присутствие неиспользуемых байтов между значениями последовательно описанных переменных

Слайд 15

Размещение данных в стековом кадре

Компилятор размещает значения переменных в стековом кадре в

Размещение данных в стековом кадре Компилятор размещает значения переменных в стековом кадре
соответствии со стандартом языка Си
Назначает переменным адреса для хранения
Переменные располагаются в стековом кадре в порядке описания
Если описаны без static/extern
Возможно присутствие неиспользуемых байтов между значениями последовательно описанных переменных

Слайд 16

Размещение данных в стековом кадре

Компилятор размещает значения переменных в стековом кадре в

Размещение данных в стековом кадре Компилятор размещает значения переменных в стековом кадре
соответствии со стандартом языка Си
Назначает переменным адреса для хранения
Переменные располагаются в стековом кадре в порядке описания
Если описаны без static/extern
Возможно присутствие неиспользуемых байтов между последовательно описанными переменными

Слайд 17

Выравнивание

Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию типа

Выравнивание Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию
T
Оператор alignof появился в C99
У всех популярных компиляторов alignof(T) -- это небольшая степень 2
Доступ к значению типа T, хранящемуся по адресу, некратному alignof(T), – это undefined behavior

char array[4] = {0};
// undefined behavior, 
// if alignof(char) %
// alignof(int) != 0
if (*(int*)array == 0) {
    // ...
}

Слайд 18

Выравнивание

Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию типа

Выравнивание Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию
T
Оператор alignof появился в C99
У всех популярных компиляторов alignof(T) -- это небольшая степень 2
Зависящая от Т
Доступ к значению типа T, хранящемуся по адресу, некратному alignof(T), – это undefined behavior

char array[4] = {0};
// undefined behavior, 
// if alignof(char) %
// alignof(int) != 0
if (*(int*)array == 0) {
    // ...
}

Слайд 19

Выравнивание

Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию типа

Выравнивание Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию
T
Оператор alignof появился в C99
У всех популярных компиляторов alignof(T) -- это небольшая степень 2
Зависящая от Т
Доступ к значению типа T, хранящемуся по адресу, некратному alignof(T), – это undefined behavior

char array[4] = {0};
// undefined behavior, 
// if alignof(char) %
// alignof(int) != 0
if (*(int*)array == 0) {
    // ...
}

Слайд 20

Выравнивание

Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию типа

Выравнивание Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию
T
Оператор alignof появился в C99
У всех популярных компиляторов alignof(T) -- это небольшая степень 2
Зависящая от Т
Доступ к значению типа T, хранящемуся по адресу, некратному alignof(T), – это undefined behavior

char array[4] = {0};
// undefined behavior, 
// if alignof(char) %
// alignof(int) != 0
if (*(int*)array == 0) {
    // ...
}

Слайд 21

Выравнивание

Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию типа

Выравнивание Значения типа Т должны храниться по адресам, кратным alignof(T) – выравниванию
T
Оператор alignof появился в C99
У всех популярных компиляторов alignof(T) -- это небольшая степень 2
Зависящая от Т
Доступ к значению типа T, хранящемуся по адресу, некратному alignof(T), – это undefined behavior

char array[4] = {0};
// undefined behavior, 
// if alignof(char) %
// alignof(int) != 0
if (*(int*)array == 0) {
    // ...
}

Слайд 22

Выравнивание простых типов и указателей

Зависит от используемого компилятора (implementation specific)
До C99 alignof(T)

Выравнивание простых типов и указателей Зависит от используемого компилятора (implementation specific) До
можно узнать в документации по компилятору
alignof(T) определяется требованиями, которые предъявляются к адресам инструкциями процессора для чтения и записи в память данных размера sizeof(T)

Слайд 23

Выравнивание простых типов и указателей

Зависит от используемого компилятора (implementation defined)
До C99 alignof(T)

Выравнивание простых типов и указателей Зависит от используемого компилятора (implementation defined) До
можно узнать в документации по компилятору
alignof(T) определяется требованиями, которые предъявляются к адресам инструкциями процессора для чтения и записи в память данных размера sizeof(T)

Слайд 24

Выравнивание простых типов и указателей

Зависит от используемого компилятора (implementation defined)
До C99 alignof(T)

Выравнивание простых типов и указателей Зависит от используемого компилятора (implementation defined) До
можно узнать в документации по компилятору
alignof(T) определяется требованиями, которые предъявляют к адресам инструкции процессора для чтения и записи в память данных размера sizeof(T)

Слайд 25

Как компилятор выравнивает производный тип

Как компилятор выравнивает производный тип

Слайд 26

Как компилятор выравнивает производный тип

Пусть T – производный тип
Пусть T1, …, Tn

Как компилятор выравнивает производный тип Пусть T – производный тип Пусть T1,
– типы элементов T
Необходимо, чтобы alignof(T) было кратно наибольшему общему кратному всех alignof(Ti)
alignof(T) % НОК(alignof(T1), …, alignof(Tn)) == 0
Иначе некоторые элементы Т будут выровнены неправильно
Все популярные компиляторы используют max вместо НОК, т.к. у них все alignof(Ti) – это степени 2

Слайд 27

Как компилятор выравнивает производный тип

Пусть T – производный тип
Пусть T1, …, Tn

Как компилятор выравнивает производный тип Пусть T – производный тип Пусть T1,
– типы элементов T
Необходимо, чтобы alignof(T) было кратно наибольшему общему кратному всех alignof(Ti)
alignof(T) % НОК(alignof(T1), …, alignof(Tn)) == 0
Иначе некоторые элементы Т будут выровнены неправильно
Все популярные компиляторы используют max вместо НОК, т.к. у них все alignof(Ti) – это степени 2

Слайд 28

Как компилятор выравнивает производный тип

Пусть T – производный тип
Пусть T1, …, Tn

Как компилятор выравнивает производный тип Пусть T – производный тип Пусть T1,
– типы элементов T
Необходимо, чтобы alignof(T) было кратно наибольшему общему кратному всех alignof(Ti)
alignof(T) % НОК(alignof(T1), …, alignof(Tn)) == 0
Иначе некоторые элементы Т будут выровнены неправильно
Все популярные компиляторы используют max вместо НОК, т.к. у них все alignof(Ti) – это степени 2

Слайд 29

Как компилятор выравнивает производный тип

Пусть T – производный тип
Пусть T1, …, Tn

Как компилятор выравнивает производный тип Пусть T – производный тип Пусть T1,
– типы элементов T
Необходимо, чтобы alignof(T) было кратно наибольшему общему кратному всех alignof(Ti)
alignof(T) % НОК(alignof(T1), …, alignof(Tn)) == 0
Иначе некоторые элементы Т могут быть выровнены неправильно
Все популярные компиляторы используют max вместо НОК, т.к. у них все alignof(Ti) – это степени 2

Слайд 30

Как компилятор выравнивает производный тип

Пусть T – производный тип
Пусть T1, …, Tn

Как компилятор выравнивает производный тип Пусть T – производный тип Пусть T1,
– типы элементов T
Необходимо, чтобы alignof(T) было кратно наибольшему общему кратному всех alignof(Ti)
alignof(T) % НОК(alignof(T1), …, alignof(Tn)) == 0
Иначе некоторые элементы Т могут быть выровнены неправильно
Все популярные компиляторы используют max вместо НОК, т.к. у них все alignof(Ti) – это степени 2

Слайд 31

Пример про выравнивание массива

T = int (*)[4] – массив из 4 int
Т1

Пример про выравнивание массива T = int (*)[4] – массив из 4
= Т2 = Т3 = Т4 = int – типы элементов Т
Пусть alignof(int) == 4, но alignof(T) == 1 или 2
т.е. нарушена кратность выравниванию элемента
Тогда разрешалось бы разместить массив int a[4] так, что
(size_t)&a % 4 == 2
И доступ к элементам a[0] и a[2] приводил бы к undefined behavior

Слайд 32

Пример про выравнивание массива

T = int (*)[4] – массив из 4 int
Т1 =

Пример про выравнивание массива T = int (*)[4] – массив из 4
Т2 = Т3 = Т4 = int – типы элементов Т
Пусть alignof(int) == 4, но alignof(T) == 1  или  2
т.е. нарушена кратность НОК(выравнивания элементов)
Тогда разрешалось бы разместить массив int a[4] так, что
(size_t)&a % 4 == 2
И доступ к элементам a[0] и a[2] приводил бы к undefined behavior

Слайд 33

Пример про выравнивание массива

T = int (*)[4] – массив из 4 int
Т1 =

Пример про выравнивание массива T = int (*)[4] – массив из 4
Т2 = Т3 = Т4 = int – типы элементов Т
Пусть alignof(int) == 4, но alignof(T) == 1  или  2
т.е. нарушена кратность НОК(выравнивания элементов)
Тогда разрешалось бы разместить массив int a[4] так, что
(size_t)&a % 4 == 2
И доступ к элементам a[0] и a[2] приводил бы к undefined behavior

Слайд 34

Пример про выравнивание массива

T = int (*)[4] – массив из 4 int
Т1 =

Пример про выравнивание массива T = int (*)[4] – массив из 4
Т2 = Т3 = Т4 = int – типы элементов Т
Пусть alignof(int) == 4, но alignof(T) == 1  или  2
т.е. нарушена кратность НОК(выравнивания элементов)
Тогда разрешалось бы разместить массив int a[4] так, что
(size_t)&a % 4 == 2
И доступ к элементам a[0] и a[2] приводил бы к undefined behavior

Слайд 35

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 36

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 37

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 38

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 39

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 40

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 41

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 42

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 43

Пример с выравниванием struct

T = struct XY { int X; double Y; }
T1 = int, T2 = double
Пусть alignof(int)

Пример с выравниванием struct T = struct XY { int X; double
≤ alignof(double) == 8, но alignof(T) == 1, 2 или 4
т.е. нарушена кратность НОК(выравнивания элементов)
Пусть a и b – переменные типа struct XY
При alignof(T) < 8 возможно (size_t)&a % 8 == A > 0, (size_t)&b % 8 == 0
При доступе к a.Y должно быть 0 == (size_t)&a.Y % 8 == ((size_t)&a + N) % 8 == (A + N) % 8
Иначе – undefined behavior
При доступе к b.Y должно быть 0 == (size_t)&b.Y % 8 == ((size_t)&b + N) % 8 == N % 8
Иначе – undefined behavior
Требование N % 8 == 0 противоречит (A + N) % 8 == 0, т.к. A > 0

Слайд 44

Выравнивающие байты в конце struct/union

Для правильного выравнивания элементов массива T требуется, чтобы

Выравнивающие байты в конце struct/union Для правильного выравнивания элементов массива T требуется,
sizeof(T) был кратен alignof(T)
Поэтому компилятор может добавлять выравнивающие байты в конце структур и объединений
см. пример про кратность выравниванию элементу структуры

struct XY {
    double X;
    char Y;
};
// В зависимости от 
// alignof(double), 
// sizeof(struct XY) == 16
// или 12

Слайд 45

Выравнивающие байты в конце struct/union

Для правильного выравнивания элементов массива T требуется, чтобы

Выравнивающие байты в конце struct/union Для правильного выравнивания элементов массива T требуется,
sizeof(T) был кратен alignof(T)
Поэтому компилятор может добавлять выравнивающие байты в конце структур и объединений
см. пример про кратность

struct XY {
    double X;
    char Y;
};
// В зависимости от 
// alignof(double), 
// sizeof(struct XY) == 16
// или 12

Слайд 46

Выравнивающие байты в конце struct/union

Для правильного выравнивания элементов массива T требуется, чтобы

Выравнивающие байты в конце struct/union Для правильного выравнивания элементов массива T требуется,
sizeof(T) был кратен alignof(T)
Поэтому компилятор может добавлять выравнивающие байты в конце структур и объединений

struct XY {
    double X;
    char Y;
};
// В зависимости от 
// alignof(double), 
// sizeof(struct XY) == 16
// или 12

Слайд 47

Выравнивающие байты в конце struct/union

Для правильного выравнивания элементов массива T требуется, чтобы

Выравнивающие байты в конце struct/union Для правильного выравнивания элементов массива T требуется,
sizeof(T) был кратен alignof(T)
Поэтому компилятор может добавлять выравнивающие байты в конце структур и объединений

struct XY {
    double X;
    char Y;
};
// В зависимости от 
// alignof(double), 
// sizeof(struct XY) == 16
// или 12

Слайд 48

Выравнивающие байты внутри struct

Компилятор может добавлять выравнивающие байты между элементами структуры для

Выравнивающие байты внутри struct Компилятор может добавлять выравнивающие байты между элементами структуры
правильного выравнивания ее элементов
см. N в примере про кратность выравниванию элементу структуры

struct YX {
    char Y;
    double X;
};
// В зависимости от 
// alignof(double), 
// sizeof(struct YX) == 16
// или 12

Слайд 49

Выравнивающие байты внутри struct

Компилятор может добавлять выравнивающие байты между элементами структуры для

Выравнивающие байты внутри struct Компилятор может добавлять выравнивающие байты между элементами структуры
правильного выравнивания ее элементов
см. N в примере про кратность выравниванию элементу структуры

struct YX {
    char Y;
    double X;
};
// В зависимости от 
// alignof(double), 
// sizeof(struct YX) == 16
// или 12

Слайд 50

Выравнивающие байты внутри struct

Компилятор может добавлять выравнивающие байты между элементами структуры для

Выравнивающие байты внутри struct Компилятор может добавлять выравнивающие байты между элементами структуры
правильного выравнивания ее элементов
см. N в примере про кратность выравниванию элементу структуры

struct YX {
    char Y;
    double X;
};
// В зависимости от 
// alignof(double), 
// sizeof(struct YX) == 16
// или 12

Слайд 51

Динамическое распределение памяти

Программа в процессе работы сама резервирует и освобождает участки памяти

Динамическое распределение памяти Программа в процессе работы сама резервирует и освобождает участки
для хранения необходимых ей данных – использует динамическое распределение памяти
Для резервирования и освобождения участка памяти используются стандартные функции языка Си
Участки памяти резервируются в специальной области памяти «куче» (heap)
Динамическое распределение памяти используется, если во время компиляции неизвестна «разумная» верхняя граница на максимальный размер обрабатываемых данных

Слайд 52

Динамическое распределение памяти

Программа в процессе работы сама резервирует и освобождает блоки памяти

Динамическое распределение памяти Программа в процессе работы сама резервирует и освобождает блоки
для хранения необходимых ей данных – использует динамическое распределение памяти
Для резервирования и освобождения участка памяти используются стандартные функции языка Си
Участки памяти резервируются в специальной области памяти «куче» (heap)
Динамическое распределение памяти используется, если во время компиляции неизвестна «разумная» верхняя граница на максимальный размер обрабатываемых данных

Слайд 53

Динамическое распределение памяти

Программа в процессе работы сама резервирует и освобождает блоки памяти

Динамическое распределение памяти Программа в процессе работы сама резервирует и освобождает блоки
для хранения необходимых ей данных – использует динамическое распределение памяти
Для резервирования и освобождения блока памяти используются стандартные функции языка Си
Участки памяти резервируются в специальной области памяти «куче» (heap)
Динамическое распределение памяти используется, если во время компиляции неизвестна «разумная» верхняя граница на максимальный размер обрабатываемых данных

Слайд 54

Динамическое распределение памяти

Программа в процессе работы сама резервирует и освобождает блоки памяти

Динамическое распределение памяти Программа в процессе работы сама резервирует и освобождает блоки
для хранения необходимых ей данных – использует динамическое распределение памяти
Для резервирования и освобождения блока памяти используются стандартные функции языка Си
Блоки памяти резервируются в специальной области памяти «куче» (heap)
Динамическое распределение памяти используется, если во время компиляции неизвестна «разумная» верхняя граница на максимальный размер обрабатываемых данных

Слайд 55

Динамическое распределение памяти

Программа в процессе работы сама резервирует и освобождает блоки памяти

Динамическое распределение памяти Программа в процессе работы сама резервирует и освобождает блоки
для хранения необходимых ей данных – использует динамическое распределение памяти
Для резервирования и освобождения блока памяти используются стандартные функции языка Си
Блоки памяти резервируются в специальной области памяти «куче» (heap)
Динамическое распределение памяти используется, если во время компиляции неизвестна «разумная» верхняя граница на максимальный размер обрабатываемых данных

Слайд 56

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 57

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 58

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 59

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 60

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 61

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 62

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 63

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 64

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 65

Стандартные функции malloc, free и др.

void* malloc(size_t size)
резервирует непрерывный блок из size

Стандартные функции malloc, free и др. void* malloc(size_t size) резервирует непрерывный блок
байтов и возвращает указатель на него
возвращает NULL, если резервирование невозможно
void* calloc(size_t count, size_t size)
резервирует непрерывный блок из count ∙ size байтов, заполняет нулями и возвращает указатель на него
возвращает NULL, если резервирование невозможно

void* realloc(void* ptr , size_t size)
резервирует непрерывный блок из size байтов и возвращает указатель на него
переносит в новый блок min(size, размер блока по адресу ptr) байтов из блока по адресу ptr и освобождает его
возвращает NULL, если изменение размера невозможно
при этом блок по адресу ptr не освобождается, данные в нем сохраняются
void free(void* ptr)
освобождает ранее зарезервированный блок по адресу ptr

Слайд 66

Doug Lea’s malloc (dlmalloc)

Основа malloc в библиотеке GNU C (libc) для большинства

Doug Lea’s malloc (dlmalloc) Основа malloc в библиотеке GNU C (libc) для
версий Linux
http://gee.cs.oswego.edu/dl/html/malloc.html

Douglas (Doug) Lea, JVM Language Summit, 2010

Слайд 67

Doug Lea’s malloc (dlmalloc)

Основа malloc в библиотеке GNU C (libc) для большинства

Doug Lea’s malloc (dlmalloc) Основа malloc в библиотеке GNU C (libc) для
версий Linux
http://gee.cs.oswego.edu/dl/html/malloc.html

Douglas (Doug) Lea, JVM Language Summit, 2010

Слайд 68

Doug Lea’s malloc (dlmalloc)

Основа malloc в библиотеке GNU C (libc) для большинства

Doug Lea’s malloc (dlmalloc) Основа malloc в библиотеке GNU C (libc) для
версий Linux
http://gee.cs.oswego.edu/dl/html/malloc.html

Douglas (Doug) Lea, JVM Language Summit, 2010

Слайд 69

Doug Lea’s malloc (dlmalloc)

Основа malloc в библиотеке GNU C (libc) для большинства

Doug Lea’s malloc (dlmalloc) Основа malloc в библиотеке GNU C (libc) для
версий Linux
http://gee.cs.oswego.edu/dl/html/malloc.html

Douglas (Doug) Lea, JVM Language Summit, 2010

Слайд 70

Устройство «кучи»

Устройство «кучи»

Слайд 71

Устройство «кучи»

Устройство «кучи»

Слайд 72

Устройство «кучи»

Устройство «кучи»

Слайд 73

Устройство «кучи»

Устройство «кучи»

Слайд 74

Устройство «кучи»

Устройство «кучи»

Слайд 75

Резервирование malloc(size)

block = свободный блок min размера ≥ size
Если block не найден,

Резервирование malloc(size) block = свободный блок min размера ≥ size Если block
то возвращаем NULL
Если размер(block) ≈ size, то возвращаем block + sizeof(size_t)
Иначе режем block на userBlock и freeBlock, чтобы размер(userBlock ) ≈ size
Добавляем freeBlock в список свободных блоков размера размер(freeBlock)
Возвращаем userBlock + sizeof(size_t)

malloc(size)

Слайд 76

Резервирование malloc(size)

block = свободный блок min размера ≥ size
Если block не найден,

Резервирование malloc(size) block = свободный блок min размера ≥ size Если block
то возвращаем NULL
Если размер(block) ≈ size, то возвращаем block + sizeof(size_t)
Иначе режем block на userBlock и freeBlock, чтобы размер(userBlock ) ≈ size
Добавляем freeBlock в список свободных блоков размера размер(freeBlock)
Возвращаем userBlock + sizeof(size_t)

malloc(size)

Слайд 77

Резервирование malloc(size)

block = свободный блок min размера ≥ size
Если block не найден,

Резервирование malloc(size) block = свободный блок min размера ≥ size Если block
то возвращаем NULL
Если размер(block) ≈ size, то возвращаем block + sizeof(size_t)
Иначе режем block на userBlock и freeBlock, чтобы размер(userBlock ) ≈ size
Добавляем freeBlock в список свободных блоков размера размер(freeBlock)
Возвращаем userBlock + sizeof(size_t)

malloc(size)

Слайд 78

Резервирование malloc(size)

block = свободный блок min размера ≥ size
Если block не найден,

Резервирование malloc(size) block = свободный блок min размера ≥ size Если block
то возвращаем NULL
Если размер(block) ≈ size, то возвращаем block + sizeof(size_t)
Иначе режем block на userBlock и freeBlock, чтобы размер(userBlock ) ≈ size
Добавляем freeBlock в список свободных блоков размера размер(freeBlock)
Возвращаем userBlock + sizeof(size_t)

malloc(size)

Слайд 79

Резервирование malloc(size)

block = свободный блок min размера ≥ size
Если block не найден,

Резервирование malloc(size) block = свободный блок min размера ≥ size Если block
то возвращаем NULL
Если размер(block) ≈ size, то возвращаем block + sizeof(size_t)
Иначе режем block на userBlock и freeBlock, чтобы размер(userBlock ) ≈ size
Добавляем freeBlock в список свободных блоков размера размер(freeBlock)
Возвращаем userBlock + sizeof(size_t)

malloc(size)

Слайд 80

Резервирование malloc(size)

block = свободный блок min размера ≥ size
Если block не найден,

Резервирование malloc(size) block = свободный блок min размера ≥ size Если block
то возвращаем NULL
Если размер(block) ≈ size, то возвращаем block + sizeof(size_t)
Иначе режем block на userBlock и freeBlock, чтобы размер(userBlock ) ≈ size
Добавляем freeBlock в список свободных блоков размера размер(freeBlock)
Возвращаем userBlock + sizeof(size_t)

malloc(size)

Слайд 81

Резервирование malloc(size)

block = свободный блок min размера ≥ size
Если block не найден,

Резервирование malloc(size) block = свободный блок min размера ≥ size Если block
то возвращаем NULL
Если размер(block) ≈ size, то возвращаем block + sizeof(size_t)
Иначе режем block на userBlock и freeBlock, чтобы размер(userBlock ) ≈ size
Добавляем freeBlock в список свободных блоков размера размер(freeBlock)
Возвращаем userBlock + sizeof(size_t)

malloc(size)

Слайд 82

Освобождение free(ptr)

Объединяем с блоком по адресу ptr блок слева (если свободен) и

Освобождение free(ptr) Объединяем с блоком по адресу ptr блок слева (если свободен)
блок справа (если свободен)
«слева» и «справа» по адресу в памяти, а не по связям в списке
Добавляем получившийся блок в список свободных блоков соотв. размера

free(ptr)

Слайд 83

Освобождение free(ptr)

Объединяем с блоком по адресу ptr блок слева (если свободен) и

Освобождение free(ptr) Объединяем с блоком по адресу ptr блок слева (если свободен)
блок справа (если свободен)
«слева» и «справа» по адресу в памяти, а не по связям в списке
Добавляем получившийся блок в список свободных блоков соотв. размера

free(ptr)

Слайд 84

Освобождение free(ptr)

Объединяем с блоком по адресу ptr блок слева (если свободен) и

Освобождение free(ptr) Объединяем с блоком по адресу ptr блок слева (если свободен)
блок справа (если свободен)
«слева» и «справа» по адресу в памяти, а не по связям в списке
Добавляем получившийся блок в список свободных блоков соотв. размера

free(ptr)

Слайд 85

Накладные расходы при работе с кучей

Поиск min свободного блока в malloc
malloc размера

Накладные расходы при работе с кучей Поиск min свободного блока в malloc
> 512 байтов и много свободных блоков в соотв. списке – большой накладной расход времени на просмотр
Дополнительные 2 ∙ sizeof(size_t) байтов на каждый блок
Много malloc небольшого размера – большой накладной расход памяти

Слайд 86

Накладные расходы при работе с кучей

Поиск min свободного блока в malloc
malloc размера

Накладные расходы при работе с кучей Поиск min свободного блока в malloc
> 512 байтов и много свободных блоков в соотв. списке – большой накладной расход времени на просмотр списка свободных блоков
Дополнительные 2 ∙ sizeof(size_t) байтов на каждый блок
Много malloc небольшого размера – большой накладной расход памяти

Слайд 87

Накладные расходы при работе с кучей

Поиск min свободного блока в malloc
malloc размера

Накладные расходы при работе с кучей Поиск min свободного блока в malloc
> 512 байтов и много свободных блоков в соотв. списке – большой накладной расход времени на просмотр списка свободных блоков
Дополнительные 2 ∙ sizeof(size_t) байтов на каждый блок
Много malloc небольшого размера – большой накладной расход памяти

Слайд 88

Фрагментация кучи

Резервирование и освобождение блоков разного размера приводит к фрагментации

for (int i = 0; i < count; ++i) {
    void* small = malloc(8);
    bigger[i] = malloc(32);
    free(small);
}

Фрагментация кучи Резервирование и освобождение блоков разного размера приводит к фрагментации for

Слайд 89

Фрагментация кучи

Резервирование и освобождение блоков разного размера приводит к фрагментации

for (int i = 0; i < count; ++i) {
    void* small = malloc(8);
    bigger[i] = malloc(32);
    free(small);
}

Фрагментация кучи Резервирование и освобождение блоков разного размера приводит к фрагментации for

Слайд 90

Фрагментация кучи

Резервирование и освобождение блоков разного размера приводит к фрагментации

for (int i = 0; i < count; ++i) {
    void* small = malloc(8);
    bigger[i] = malloc(32);
    free(small);
}

Фрагментация кучи Резервирование и освобождение блоков разного размера приводит к фрагментации for

Слайд 91

Фрагментация кучи

Резервирование и освобождение блоков разного размера приводит к фрагментации

for (int i = 0; i < count; ++i) {
    void* small = malloc(8);
    bigger[i] = malloc(32);
    free(small);
}

Фрагментация кучи Резервирование и освобождение блоков разного размера приводит к фрагментации for

Слайд 92

Фрагментация кучи

Резервирование и освобождение блоков разного размера приводит к фрагментации
Свободная память разбита

Фрагментация кучи Резервирование и освобождение блоков разного размера приводит к фрагментации Свободная
на большое число мелких блоков и нет возможности зарезервировать блоки большего размера

for (int i = 0; i < count; ++i) {
    void* small = malloc(8);
    bigger[i] = malloc(32);
    free(small);
}

Слайд 93

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// freeing invalid pointer
free(&ptr); 
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
 // heap corruption
    ptr[i-1] = 0;

Виды ошибок при работе с кучей // missing NULL pointer check int*
// <--
}

Слайд 94

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 95

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 96

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 97

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 98

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 99

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 100

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 101

Виды ошибок при работе с кучей

// missing NULL pointer check
int* ptr = malloc(4);
*ptr = 0; // <--
free(ptr);
*ptr = 0; // use after free
free(ptr); // double free
// freeing invalid pointer
ptr = malloc(8);
free(ptr + 4); // <--
free(&ptr);  // <--

// memory leak
ptr = malloc(8);
ptr = malloc(8); // <--
// memory leak
ptr = realloc(ptr,

Виды ошибок при работе с кучей // missing NULL pointer check int*
32); // <-- if OOM
// heap corruption
ptr = malloc(4);
for (int i = 0; i < 10; ++i) {
    ptr[i - 1] = 0; // <-- if i = 0
}

Слайд 102

Address sanitizer

Константин Серебряный1
Derek Bruening2
Александр Потапенко3
Дмитрий Вьюков4
AddressSanitizer: A Fast Address Sanity Checker
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37752.pdf

1

2

3

4

Address sanitizer Константин Серебряный1 Derek Bruening2 Александр Потапенко3 Дмитрий Вьюков4 AddressSanitizer: A

Слайд 103

Address sanitizer

Константин Серебряный1
Derek Bruening2
Александр Потапенко3
Дмитрий Вьюков4
AddressSanitizer: A Fast Address Sanity Checker
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37752.pdf

Address sanitizer Константин Серебряный1 Derek Bruening2 Александр Потапенко3 Дмитрий Вьюков4 AddressSanitizer: A

Слайд 104

Address sanitizer

Константин Серебряный1
Derek Bruening2
Александр Потапенко3
Дмитрий Вьюков4
AddressSanitizer: A Fast Address Sanity Checker
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37752.pdf

1

2

3

4

Address sanitizer Константин Серебряный1 Derek Bruening2 Александр Потапенко3 Дмитрий Вьюков4 AddressSanitizer: A

Слайд 105

Address sanitizer

Константин Серебряный1
Derek Bruening2
Александр Потапенко3
Дмитрий Вьюков4
AddressSanitizer: A Fast Address Sanity Checker, 2012
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/37752.pdf

1

2

3

4

Address sanitizer Константин Серебряный1 Derek Bruening2 Александр Потапенко3 Дмитрий Вьюков4 AddressSanitizer: A

Слайд 106

Use after free

Use after free

Слайд 107

Buffer overflow (heap corruption)

Buffer overflow (heap corruption)