Table of Contents
Вопросы управления памятью в C++
Зачем мне надо знать что-либо о памяти?
- не хочешь работать с памятью - зачем ты тогда юзаешь C++, а не другой язык, на котором разработка ведется во много раз быстрее?
Введение в память
Что делают с памятью
- выделение памяти
- освобождение памяти - С++ FAQ
- как можно поступать - автоматический подход: сборка мусора, умные указатели против ручного подхода - new и delete
- обращение к памяти
- что будет, если обратиться и начать изменять значения в памяти, которая была освобождена. Жизнь после delete, жизнь после выхода из блока для автоматической переменной. Опасный г*код. delete this
тут же: почему нельзя натравить delete/free на указатель дважды? Это приведет к попытке дважды удалить адрес из списка “занятых”
Типы памяти
Str:В9. Управление памятью Sut:6.1
статическая
- в ней помещаются глобальные переменные, переменные из пространств имен, статические переменные из классов и функций. Объект помещается в статическую память линкером. Объект имеет один и тот же адрес, он конструируется один раз.
Str:10.4.8. Локальная статическая память Std:3.7.1 Static storage duration
Str:10.4.9. Нелокальная память – статики и глобалы. Std: 3.6.2 Initialization of non-local objects
Автоматическая(стек)
- объекты конструируются в точке определения и уничтожеаются в конце области видимости
Str:10.4.4. Локальные переменные Std:3.7.2 Automatic storage duration \
Константы
- Значения данных известны во время компиляции и жестко зашиты в исполняемый файл. Если захочешь привести подобные данные const_cast'ом – ничего не выйдет. Если, обнаглев, попробуешь изменить их по указателю – получишь по башне segmentation fault'ом.
- не всякая фигня, объявленная с квалификатором const, будет располагаться в области константных данных. константы в автоматической памяти, инициализируемых из аргумента функции, лежат в обычной автоматической памяти, а потому могут быть изменены после const_cast.
Динамическая/свободная
- выделяется и освобождается вручную с помощью new,delete
Str:10.4.5., 6.2.6 Свободная память размещаемая new. Std:3.7.3 Dynamic storage duration
Куча
- выделяется и освобождается вручную с помощью malloc/free.
Когда какой памяти надо отдавать предпочтение?
- если хочешь, чтобы объект долго жил (а именно, жил после выхода из области видимости) и собираешься сам управлять его временем создания и уничтожения – динамическая.
- если объект временный – автоматическая
Проблемы, связанные с памятью
- memory leaks - забыл delete. Пример на работу с массивами.
- фрагментация памяти. Почему бы избегаем фрагментации, а не дефрагментируем иногда память?
- запись/чтение по адресам, которые тебе не принадлежат
Типы данных C++ и выделяемая память
- sizeof(). Для каких типов определен Стандартом (Std:5.3.3/1), а где зависит от реализации? Какие выводы надо сделать, чтобы не попасть впросак при переходе с одной платформы на другую. Sizeof вычисляется на стадии компиляции.
- чему равен sizeof структуры (Std:5.3.3/2), класса с виртуальными функциями, класса без членов-данных, union'a (Std:9.5 Unions), указателя, указателя на функцию-член, объект инстанцированного шаблона класса, разыменованного указателя на полиморфный объект, битового поля
- что такое POD-типы - ни тебе инкапсуляции, ни других ОО-фич (Std:3.9/10, 9/4)
- расположение в памяти классов. Наследование, множественное наследование, виртуальное наследование. Nested-классы, local-классы - механизмы, корректирующие область видимости и к расположению в памяти не имеющие никакого отношения.
- указатели на члены-данные - что они такое? А указатели на члены-функции?
Часть 2
Свойства памяти
Выравнивание
- что такое выравнивание и от чего оно зависит. Std:3.9/1, 3.9.1, 3.9.2.
Интересные примеры по выравниванию. Как можно уменьшить размер структуры, переместив в ней поля? Выравнивание и заполнение (padding).
Например, структура Padd2a будет занимать 1 (+1) + 2 + 4 (+4)=8 байт
struct Padd2a { char a; short b; int c; char d; };
А структура Padd2b займет всего 1+1+2+4 байта
struct Padd2b { char a; char d; short b; int c; };
- Где я могу столкнуться с выравниванием? При вычислении sizeof битовых полей, при соседстве невыровненных даных с выровненными (например, sizeof структуры, состоящей из одного чара и одного инта будет 4+4=8, а вовсе не 1+4=5.)
- обязательно надо озаботиться вопросами выравнивания когда посылаешь сырые данные по сети.
- как поступают с выравниванием - в случае больших дырок юзают pragma pack.
Endianness
- что такое big-endian и little-endian Wikipedia Википедия. Как узнать, что за порядок байтов на твоей машине?
- мы сталкиваемся с endiann'остью когда работаем с сокетами - функция hton.
- мы врезаемся в endiann'ость, когда по своей дури пользуемся битовыми полями – смотри endians.cpp для кровавых деталей.
Средства, унаследованные от C
Выделение/освобождение
- malloc, free, realloc, calloc - что делают? Зачем C++-программисту знать такие вещи? Как их используют? Лулз: 20.4.6/3 The functions calloc(), malloc(), and realloc() do not attempt to allocate storage by calling ::operator new(); 20.4.6/4 The function free() does not attempt to deallocate storage by calling ::operator delete().
Почему не стоит использовать в C++?
Заполнение
- memset, memcpy, memmove
Альтернативы им в C++
Std:20.4.4.1-20.4.4.3; Jos 15.2 * Fill (ForwardIterator first, ForwardIterator last, const T& value) - заполняет значением value весь промежуток Std:25.2.5 * uninitialized_fill(first,last,value) - пока не понял * uninitialized_copy(first,last,first2) -
- работа со строками C
Мапенье
- mmap
- файл /proc/<num>/maps - содержит отображение памяти, смотри man -5 proc
new/delete -- введение
Std:5.3.4/9 New
Std:5.3.5 Delete
new
- почему не malloc() ? Потому что конструктор!
- Когда вызывается new, а когда нет? Как взаимодействует new с конструктором (кто раньше, кто позже)? Функция construct
delete
- Разрушение объекта и очистка памяти, выделенной под него.
- delete ведет себя как виртуальный при виртуальном деструкторе.
- Почему нельзя натравить delete на указатель дважды?
- почему можно натравить delete на нулевой указатель?
- константный объект - что там ? ссылка
Определение поведения при выделении и освобождении памяти
свои ::operator new() и ::operator delete()
- сигнатура:
void* operator new(size_t); void operator delete(void*)
- Для кого они вызываются? Когда их нужно определять
- для целей дебага. нахождение ошибок: выход за границу массива, поиск мемликов
- ведение статистики: распределение блоков по размерам, порядок выделения/освобождения, максимальный объем выделенной памяти, время жизни блоков
- повышение производительности - принудительное выравнивание double
Std 3.7.3.1 Allocation functions
Std: 3.7.3.2 Deallocation functions
свои operator new() и operator delete()
- запрет на размещение объекта в динамической памяти.
- содействие размещению объекта в динамической памяти
Когда есть смысл перегружать new/delete для классов? См. Mey:50
- для того, чтобы избежать фрагментации памяти при плохом распределителе памяти – пулы для аллокации
- для того, чтобы ограничить возможную утечку памяти это лишь фантазия, возможно, я не прав
Как это делать?:
- детский пример (с использованием malloc/free) код
- как устроено на самом деле (по умолчанию)
Какие грабли нас поджидают:
- исключения
- непарные new/delete
- путанье глобального и локального new/delete
- невиртуальныей деструктор (Sut:6.2, Dew:36)
- наследование new и delete (Mey:49). Как избежать
Обработчик new - new_handler
- set_new_handler позволяет переопределить функцию, которая вызывается в случае, когда new не может выделить память. Сигнатура:
namespace std{
typedef void (*new_handler)(); new handler set_new_handler(new_handler p) throw(); }
Std:3.7.3.1/3
An allocation function that fails to allocate storage can invoke the currently installed new_handler (18.4.2.2), if any. [Note: A program-supplied allocation function can obtain the address of the currently installed new_handler using the set_new_handler function (18.4.2.3).] * описание функции находится в Std:18.4.2.3 , замечания по использованию в Mey:49,51 . Этой фу
new[] и delete []
- Тоже самое для массивов.
Размещающий ::operator new
Str:10.4.11 Размещение объектов
Пример использования
- ссылка на гуглкод
Когда это бывает полезно
- например, когда у нас две оперативных памяти.
- еще???
nothrow new
Widget *wid = new (std::nothrow) Widget; if (wid==0) { ... }
- история возникновения - когда-то не было исключений и вместо выброса bad_alloc new возвращал нулевой указатель. Сейчас не так.
- nothrow new дает только гарантии, что он сам не выбсорит исключений. Стоит выброситься исключению в конструкторе - и все будет как обычно.
Mey:49
STL
- capacity(), size(), max_size(), у контейнеров
Аллокаторы
- как работает обычный аллокатор? какие требования к нему предъявляются? связанное
- когда стоит писать свой аллокатор? еще ссылка Требования к аллокаторам. (allocate, construct,destroy,deallocate, типы ссылки и указателя и т.п. ) Jos:15
- Грабли ( по идее, не стоит использовать разные распределители в одной программе). Какие аллокаторы могут улучшить произваодительность и в какх случаях? intel tbbs, его юзанье
- raw_storage_iterator Std:20.4.2 Str:19.4.2
Не знаю, куда относить
- ссылки
- операторы приведения – как работаю с точки зрения памяти
- виртуальные функции. Таблица виртуальных функций
- арифметика указателей
- garbage-collector'ы
- умные указатели
- raw_storage_iterator Std:20.4.2 Str:19.4.2
Литература
- Str - Stroustroup The C++ Programming Language
- Jos - Josuttis The C++ Standard Library
- Std - C++ Standard ISO/IEC 14882
- Sut - Sutter Exceptional C++
- Dew – Stepher C.Dewhurst C++ Common Knowledge
- Mey – Effective C++
Решенные вопросы
- что делать не позволено операционной системой?
менять настоящие константы – они сидят в одной из секций ELF-файла. Обращаться к памяти, на которую ты не замапен.
- когда нужны собственные аллокаторы STL?
пока не понимаю
- что изменится с выходом 0x ?
Отв: Мало что, появится слово auto
- как работает стандартные new/delete в общих чертах?
вызывают malloc/free и вызывают конструктор для не-POD-типов
- у нас есть typeid. Где хранится инфа о типе? Она хранится для каждого объекта? Для типа?
- аллокатор, обеспечивающий thread safety
я пока не понял как делать аллокатор, да и thread safety знаю понаслышке. Устранить пробелы