Open Source & Linux Lab

It's better when it's simple

User Tools

Site Tools


etc:users:yuri_v_katkov:cpp_memory

Вопросы управления памятью в 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) - FIXME пока не понял * uninitialized_copy(first,last,first2) -

  • работа со строками C

Мапенье

  • mmap FIXME
  • файл /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

  • для того, чтобы избежать фрагментации памяти при плохом распределителе памяти – пулы для аллокации
  • для того, чтобы ограничить возможную утечку памяти DELETEME это лишь фантазия, возможно, я не прав

Как это делать?:

  • детский пример (с использованием 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 Размещение объектов

Пример использования

  • FIXME ссылка на гуглкод

Когда это бывает полезно

  • например, когда у нас две оперативных памяти.
  • еще??? FIXME

nothrow new

Widget *wid = new (std::nothrow) Widget;
if (wid==0)
{
  ...
} 
  • история возникновения - когда-то не было исключений и вместо выброса bad_alloc new возвращал нулевой указатель. Сейчас не так.
  • nothrow new дает только гарантии, что он сам не выбсорит исключений. Стоит выброситься исключению в конструкторе - и все будет как обычно.

Mey:49

STL

  • capacity(), size(), max_size(), у контейнеров

Аллокаторы

Не знаю, куда относить

Литература

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

You could leave a comment if you were logged in.
etc/users/yuri_v_katkov/cpp_memory.txt · Last modified: 2016/08/08 20:53 by kel