Вопросы управления памятью в 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'ы

умные указатели

boost-pool

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 знаю понаслышке. Устранить пробелы