core.memory
Этот модуль предоставляет интерфейс к сборщику мусора, используемому приложениями, написанными на языке программирования D. Он позволяет заменить сборщик мусора в среде выполнения без влияния на бинарную совместимость приложений.
Использование этого модуля не обязательно в типичном коде D. Он в основном полезен при выполнении низкоуровневого управления памятью.
- Примечания для пользователей
- Сборщик мусора (GC) — это консервативный сборщик по методу «маркировка-уборка». Он запускает цикл сбора только при запросе выделения памяти, в противном случае нет. Следовательно, если программа не выполняет выделение памяти, не будет и пауз сбора мусора. Паузы происходят, потому что все известные сборщику мусора потоки приостанавливаются, чтобы можно было просканировать стеки и регистры потоков на предмет ссылок на выделенную сборщиком мусора память.
- Сборщик мусора (GC) не знает о потоках, созданных путем непосредственного вызова API создания потоков операционной системы/C и потоках D, которые были отделены от среды выполнения D после создания. Такие потоки не будут приостановлены для сбора мусора, и сборщик мусора может не обнаружить ссылки на выделенную им память, удерживаемую этими потоками. Это может привести к повреждению памяти. Существует несколько способов решения этой проблемы:
- Не удерживайте ссылки на выделенную сборщиком мусора память в таких потоках.
- Регистрируйте/удаляйте такую память с помощью вызовов
addRoot/removeRootиaddRange/removeRange. - Сохраняйте другую ссылку на ту же самую данные в другом потоке, о котором знает GC.
- Отключите циклы сбора мусора во время активности этого потока с помощью
disable/enable. - Зарегистрируйте поток в GC с помощью
core.thread.thread_attachThis/core.thread.thread_detachThis.
- Примечания для разработчиков
- В системах POSIX сигналы SIGUSR1 и SIGUSR2 зарезервированы этим модулем для использования в реализации сборщика мусора. Как правило, они будут использоваться для остановки и возобновления других потоков при выполнении сбора, но реализация может выбрать не использовать этот механизм (или вообще не останавливать мир в случае конкурирующих сборщиков мусора).
- Регистры, стек и любые другие места в памяти, добавленные через функцию
GC.addRange, всегда сканируются консервативным способом. Это означает, что даже если переменная, например, имеет типfloat, она всё равно будет просканирована на предмет возможных указателей GC. И если интерпретируемое по слову представление переменной соответствует адресу блока памяти, управляемого GC, этот блок памяти считается живым. - Реализации могут свободно сканировать кучу, не являющуюся корнем, точным способом, чтобы поля типов, подобных
float, не считались релевантными при сканировании кучи. Таким образом, приведение указателя GC к целочисленному типу (например,size_t) и его хранение в поле такого типа внутри кучи GC может означать, что он не будет распознан, если блок памяти был выделен с точной информацией о типе или с атрибутомGC.BlkAttr.NO_SCAN. - Деструкторы всегда будут выполняться при активности других потоков; то есть реализация, останавливающая мир, не должна выполнять деструкторы, пока мир не возобновлён.
- Деструктор объекта не должен обращаться к ссылкам на объекты внутри объекта. Это означает, что реализация может свободно оптимизировать на основе этого правила.
- Реализация может свободно выполнять уплотнение и копирование кучи, при условии, что при этом не будут аннулированы действительные указатели GC. Однако память, выделенная с помощью
GC.BlkAttr.NO_MOVE, не должна перемещаться/копироваться. - Реализации должны поддерживать внутренние указатели. То есть, если единственная ссылка на блок памяти, управляемый GC, указывает на середину блока, а не на начало (например), GC должен рассматривать блок памяти как живой. Исключение из этого правила — когда блок памяти выделяется с атрибутом
GC.BlkAttr.NO_INTERIOR; ответственность пользователя заключается в обеспечении наличия надлежащего указателя на такие блоки памяти, когда они должны считаться живыми. - Допустимо, чтобы реализация хранила битовые флаги в значениях указателей и управляемых GC блоках памяти, при условии, что такой трюк не виден приложению. На практике это означает, что только сборщик мусора «останови-мир» может это делать.
- Реализации могут свободно предполагать, что указатели GC хранятся только на границах слов. Невыровненные указатели могут быть полностью проигнорированы.
- Реализации могут свободно запускать сборы в любой момент. Однако рекомендуется делать это только тогда, когда попытка выделения памяти происходит и свободной памяти недостаточно.
- Лицензия:
- Boost License 1.0
- Авторы:
- Шон Келли, Алекс Рённе Петерсен
- Исходный код
- core/memory.d
- immutable size_t pageSize;
-
Размер страницы системы в байтах.
Это значение устанавливается при запуске приложения. Его безопасно использовать на ранней стадии процесса запуска, например, в конструкторах общих модулей и при инициализации среды выполнения D.
- Примеры:
-
ubyte[] buffer = new ubyte[pageSize];
- struct GC;
-
Данная структура инкапсулирует все функции сборки мусора для языка программирования D.
- struct Stats;
-
Агрегация данных статистики GC для экспонирования через публичный API
- size_t usedSize;
-
количество используемых байтов в куче GC (может обновляться только после сбора мусора)
- size_t freeSize;
-
количество свободных байтов в куче GC (может обновляться только после сбора мусора)
- ulong allocatedInCurrentThread;
-
количество байтов, выделенных для текущего потока с момента запуска программы
- struct ProfileStats;
-
Агрегация текущей информации профилирования
- size_t numCollections;
-
общее количество циклов GC
- Duration totalCollectionTime;
-
общее время, потраченное на сбор мусора
- Duration totalPauseTime;
-
общее время, в течение которого потоки были приостановлены во время сбора мусора
- Duration maxPauseTime;
-
наибольшее время, в течение которого потоки были приостановлены во время одного цикла GC
- Duration maxCollectionTime;
-
наибольшее время, потраченное на один цикл GC
- static nothrow void enable();
-
Включает автоматическую сборку мусора, если сборка была ранее приостановлена вызовом disable. Эта функция реентерабельна и должна вызываться один раз для каждого вызова disable перед включением автоматической сборки мусора.
- static nothrow void disable();
-
Отключает автоматическую сборку мусора для минимизации использования ресурсов процесса. Сбор мусора может по-прежнему выполняться в случаях, когда реализация считает это необходимым для корректной работы программы, например, при недостатке памяти. Данная функция реентерабельна, но enable должна вызываться один раз для каждого вызова disable.
- static nothrow void collect();
-
Начинает полный сбор мусора. Значение этого может меняться в зависимости от реализации сборщика мусора, но типичное поведение заключается в сканировании всех сегментов стека на наличие корней, помечая доступные блоки памяти как живые, а затем освобождая свободное пространство. Для выполнения этого действия может потребоваться приостановка всех запущенных потоков как минимум на части процесса сбора мусора.
- static nothrow void minimize();
-
Указывает, что область управляемой памяти должна быть минимизирована путём возвращения свободной физической памяти операционной системе. Количество возвращённой памяти зависит от дизайна аллокатора и поведения программы.
- enum BlkAttr: uint;
-
Элементы для битового поля, представляющего атрибуты блока памяти. Они управляются функциями getAttr, setAttr и clrAttr.
- NONE
-
Нет установленных атрибутов.
- FINALIZE
-
Выполнить финализацию данных в этом блоке при сборе мусора.
- NO_SCAN
-
Не сканировать этот блок при сборе мусора.
- NO_MOVE
-
Не перемещать этот блок памяти при сборе мусора.
- APPENDABLE
-
Этот блок содержит информацию для поддержки добавления элементов.
Это можно использовать для ручного выделения массивов. Начальный размер слайса равен 0.
- Примечание
- Использованный размер слайса не будет соответствовать размеру блока. Используйте
capacityдля получения фактической емкости.
- Пример
// Allocate the underlying array. int* pToArray = cast(int*)GC.malloc(10 * int.sizeof, GC.BlkAttr.NO_SCAN | GC.BlkAttr.APPENDABLE); // Bind a slice. Check the slice has capacity information. int[] slice = pToArray[0 .. 0]; assert(capacity(slice) > 0); // Appending to the slice will not relocate it. slice.length = 5; slice ~= 1; assert(slice.ptr == p);
- NO_INTERIOR
-
Этот блок гарантированно содержит указатель на его базовый адрес, пока он активен. Внутренние указатели можно безопасно игнорировать. Этот атрибут полезен для исключения ложных указателей в очень больших структурах данных и реализован только для структур данных, размер которых составляет не менее страницы.
- alias BlkInfo = .BlkInfo_;
-
Содержит агрегированную информацию о блоке управляемой памяти. Цель этой структуры - обеспечить более эффективный стиль запросов в случаях, когда требуется подробная информация.
base = указатель на начало блока. size = размер блока, вычисленный из base. attr = биты атрибутов, установленные в блоке памяти.
- static nothrow uint getAttr(scope const void* p);
static pure nothrow uint getAttr(void* p); -
Возвращает битовое поле, представляющее все атрибуты блока, установленные для памяти, на которую ссылается p. Если p ссылается на память, первоначально не выделенную этим сборщиком мусора, указывает на внутреннюю часть блока памяти или если p равно null, возвращается ноль.
- Параметры:
void* pУказатель на начало корректного блока памяти или null.
- Возвращает:
- Битовое поле, содержащее любые биты, установленные для блока памяти, на который ссылается p, или ноль при ошибке.
- static nothrow uint setAttr(scope const void* p, uint a);
static pure nothrow uint setAttr(void* p, uint a); -
Устанавливает указанные биты для ссылки на память p. Если p ссылается на память, первоначально не выделенную этим сборщиком мусора, указывает на внутреннюю часть блока памяти или если p равно null, никаких действий не выполняется.
- Параметры:
void* pУказатель на начало корректного блока памяти или null. uint aБитовое поле, содержащее любые биты для установки в этом блоке памяти.
- Возвращает:
- Результат вызова getAttr после установки указанных битов.
- static nothrow uint clrAttr(scope const void* p, uint a);
static pure nothrow uint clrAttr(void* p, uint a); -
Сбрасывает указанные биты для ссылки на память p. Если p ссылается на память, первоначально не выделенную этим сборщиком мусора, указывает на внутреннюю часть блока памяти или если p равно null, никаких действий не выполняется.
- Параметры:
void* pУказатель на начало корректного блока памяти или null. uint aБитовое поле, содержащее любые биты для сброса в этом блоке памяти.
- Возвращает:
- Результат вызова getAttr после сброса указанных битов.
- static pure nothrow void* malloc(size_t sz, uint ba = 0, const TypeInfo ti = null);
-
Запрашивает выровненный блок управляемой памяти у сборщика мусора. Эта память может быть удалена по желанию с помощью вызова free или может быть отброшена и очищена автоматически во время цикла сбора мусора. Если выделение памяти не удалось, эта функция вызовет onOutOfMemory, которая ожидает бросить исключение OutOfMemoryError.
- Параметры:
size_t szЖелаемый размер выделения в байтах. uint baМаска битов атрибутов для установки в этом блоке. TypeInfo tiTypeInfo для описания памяти. GC может использовать эту информацию для улучшения сканирования указателей или вызова финализаторов.
- Возвращает:
- Ссылка на выделенную память или null, если памяти недостаточно.
- Исключение:
- OutOfMemoryError при неудачном выделении.
- static pure nothrow BlkInfo qalloc(size_t sz, uint ba = 0, const TypeInfo ti = null);
-
Запрашивает выровненный блок управляемой памяти у сборщика мусора. Эта память может быть удалена по желанию с помощью вызова free или может быть отброшена и очищена автоматически во время цикла сбора мусора. Если выделение памяти не удалось, эта функция вызовет onOutOfMemory, которая ожидает бросить исключение OutOfMemoryError.
- Параметры:
size_t szЖелаемый размер выделения в байтах. uint baМаска битов атрибутов для установки в этом блоке. TypeInfo tiTypeInfo для описания памяти. GC может использовать эту информацию для улучшения сканирования указателей или вызова финализаторов.
- Возвращает:
- Информация о выделенном блоке памяти или BlkInfo.init при ошибке.
- Исключение:
- OutOfMemoryError при неудачном выделении.
- static pure nothrow void* calloc(size_t sz, uint ba = 0, const TypeInfo ti = null);
-
Запрашивает выровненный блок управляемой памяти у сборщика мусора, который инициализируется всеми битами, установленным в ноль. Эта память может быть удалена по желанию с помощью вызова free или может быть отброшена и очищена автоматически во время цикла сбора мусора. Если выделение памяти не удалось, эта функция вызовет onOutOfMemory, которая ожидает бросить исключение OutOfMemoryError.
- Параметры:
size_t szЖелаемый размер выделения в байтах. uint baМаска битов атрибутов для установки в этом блоке. TypeInfo tiTypeInfo для описания памяти. GC может использовать эту информацию для улучшения сканирования указателей или вызова финализаторов.
- Возвращает:
- Ссылка на выделенную память или null, если памяти недостаточно.
- Исключение:
- OutOfMemoryError при неудачном выделении.
- static pure nothrow void* realloc(void* p, size_t sz, uint ba = 0, const TypeInfo ti = null);
-
Расширить, уменьшить или выделить новый блок памяти, сохранив содержимое существующего блока
Если
szравно нулю, память, на которую ссылается p, будет освобождена так, как если бы был вызванfree. Еслиpравноnull, новая память будет выделена черезmalloc. Еслиpуказывает на память, не выделенную сборщиком мусора или на внутреннюю область выделенного блока памяти, никакая операция не выполняется, и возвращается null.
В противном случае будет выделен новый блок памяти размеромsz, как если бы был вызванmalloc, или реализация может вместо этого изменить размер или уменьшить блок памяти на месте. Содержимое нового блока памяти будет таким же, как содержимое старого блока памяти, до меньшего из нового и старого размеров.
Вызывающий метод гарантирует, что нет других активных указателей на переданный блок памяти, но он может не быть освобожден немедленноrealloc. Сборщик мусора может вернуть блок памяти в более поздней коллекции, если он не используется. Если выделение памяти завершилось неудачно, эта функция выброситOutOfMemoryError.
Еслиbaравно нулю (по умолчанию), атрибуты существующей памяти будут использованы для выделения. Еслиbaне равно нулю и новая память не выделяется, биты в ba заменят биты текущего блока памяти.- Параметры:
void* pУказатель на начало допустимого блока памяти или на null.size_t szЖелаемый размер выделения в байтах. uint baМаска битов атрибутов BlkAttr для установки для этого блока. TypeInfo tiTypeInfo для описания памяти. Сборщик мусора может использовать эту информацию для улучшения сканирования указателей или для вызова финализаторов.
- Возвращает:
- Ссылка на выделенную память при успехе или
null, еслиszравно нулю или указатель не указывает на начало блока памяти, выделенного сборщиком мусора.
- Выбрасывает:
-
OutOfMemoryErrorпри ошибке выделения.
- Примеры:
-
enum size1 = 1 << 11 + 1; // page in large object pool enum size2 = 1 << 22 + 1; // larger than large object pool size auto data1 = cast(ubyte*)GC.calloc(size1); auto data2 = cast(ubyte*)GC.realloc(data1, size2); GC.BlkInfo info = GC.query(data2); assert(info.size >= size2);
- static pure nothrow size_t extend(void* p, size_t mx, size_t sz, const TypeInfo ti = null);
-
Запрашивает расширение управляемого блока памяти, на который указывает p, на месте как минимум на mx байт, с желаемым расширением на sz байт. Если расширение требуемого размера невозможно или если p ссылается на память, не выделенную первоначально этим сборщиком мусора, никаких действий не будет предпринято.
- Параметры:
void* pУказатель на начало допустимого блока памяти или на null. size_t mxМинимальный размер расширения в байтах. size_t szЖелаемый размер расширения в байтах. TypeInfo tiTypeInfo для описания всего блока памяти. Сборщик мусора может использовать эту информацию для улучшения сканирования указателей или для вызова финализаторов.
- Возвращает:
- Размер расширенного блока памяти, на который указывает p, в байтах или ноль, если расширение не произошло.
- Примечание
- Расширение также может использоваться для расширения слайсов (или блоков памяти с
APPENDABLEинформацией). Однако используйте возвращаемое значение только как индикатор успеха.capacityследует использовать для получения фактической емкости используемого слайса.
- Примеры:
- Стандартное расширение
size_t size = 1000; int* p = cast(int*)GC.malloc(size * int.sizeof, GC.BlkAttr.NO_SCAN); //Try to extend the allocated data by 1000 elements, preferred 2000. size_t u = GC.extend(p, 1000 * int.sizeof, 2000 * int.sizeof); if (u != 0) size = u / int.sizeof;
- Примеры:
- Расширение слайса
int[] slice = new int[](1000); int* p = slice.ptr; //Check we have access to capacity before attempting the extend if (slice.capacity) { //Try to extend slice by 1000 elements, preferred 2000. size_t u = GC.extend(p, 1000 * int.sizeof, 2000 * int.sizeof); if (u != 0) { slice.length = slice.capacity; assert(slice.length >= 2000); } }
- static nothrow size_t reserve(size_t sz);
-
Запрашивает выделение как минимум sz байт памяти из операционной системы и помечает её как свободную.
- Параметры:
size_t szЖелаемый размер в байтах.
- Возвращает:
- Фактическое количество зарезервированных байт или ноль при ошибке.
- static pure nothrow @nogc void free(void* p);
-
Освобождает память, на которую указывает p. Если p равно null, никаких действий не происходит. Если p ссылается на память, не выделенную первоначально этим сборщиком мусора, если p указывает на внутреннюю область блока памяти, или если этот метод вызывается из финализатора, никаких действий не будет предпринято. Блок не будет финализирован независимо от того, установлен ли атрибут FINALIZE. Если требуется финализация, вызовите
destroyпередGC.free.- Параметры:
void* pУказатель на начало допустимого блока памяти или на null.
- static nothrow @nogc inout(void)* addrOf(inout(void)* p);
static pure nothrow @nogc void* addrOf(void* p); -
Возвращает базовый адрес блока памяти, содержащего p. Это значение полезно для определения, является ли p внутренним указателем, и результат может быть передан в такие процедуры, как sizeOf, которые в противном случае могут завершиться неудачей. Если p ссылается на память, не выделенную первоначально этим сборщиком мусора, если p равно null или сборщик мусора не поддерживает эту операцию, будет возвращен null.
- Параметры:
inout(void)* pУказатель на корень или внутреннюю область допустимого блока памяти или на null.
- Возвращает:
- Базовый адрес блока памяти, на который указывает p, или null при ошибке.
- static nothrow @nogc size_t sizeOf(scope const void* p);
static pure nothrow @nogc size_t sizeOf(void* p); -
Возвращает истинный размер блока памяти, на который указывает p. Это значение представляет максимальное количество байт, для которого вызов realloc может изменить размер существующего блока на месте. Если p ссылается на память, не выделенную первоначально этим сборщиком мусора, указывает на внутреннюю область блока памяти или если p равно null, будет возвращено ноль.
- Параметры:
void* pУказатель на начало допустимого блока памяти или на null.
- Возвращает:
- Размер блока памяти, на который указывает p, в байтах или ноль при ошибке.
- static nothrow BlkInfo query(scope const void* p);
static pure nothrow BlkInfo query(void* p); -
Возвращает агрегированную информацию о блоке памяти, содержащем p. Если p ссылается на память, не выделенную первоначально этим сборщиком мусора, если p равно null или сборщик мусора не поддерживает эту операцию, будет возвращена BlkInfo.init. Как правило, поддержка этой операции зависит от поддержки операции addrOf.
- Параметры:
void* pУказатель на корень или внутреннюю область допустимого блока памяти или на null.
- Возвращает:
- Информация о блоке памяти, на который указывает p, или BlkInfo.init при ошибке.
- static nothrow Stats stats();
-
Возвращает статистику выполнения для текущей активной реализации сборщика мусора. См.
core.memory.GC.Statsдля списка доступных метрик. - static nothrow @nogc @safe ProfileStats profileStats();
-
Возвращает статистику выполнения профиля для текущей активной реализации сборщика мусора. См.
core.memory.GC.ProfileStatsдля списка доступных метрик. - static nothrow @nogc void addRoot(const void* p);
-
Добавляет внутренний корень, указывающий на блок памяти сборщика мусора, на который указывает p. В результате, блок, на который указывает p сам по себе, и любые блоки, доступные через него, будут считаться активными до тех пор, пока корень не будет удалён снова.
Если p равно null, никакой операции не выполняется.
- Параметры:
void* pУказатель в блок памяти, управляемый сборщиком мусора, или null.
- Пример
// Typical C-style callback mechanism; the passed function // is invoked with the user-supplied context pointer at a // later point. extern(C) void addCallback(void function(void*), void*); // Allocate an object on the GC heap (this would usually be // some application-specific context data). auto context = new Object; // Make sure that it is not collected even if it is no // longer referenced from D code (stack, GC heap, …). GC.addRoot(cast(void*)context); // Also ensure that a moving collector does not relocate // the object. GC.setAttr(cast(void*)context, GC.BlkAttr.NO_MOVE); // Now context can be safely passed to the C library. addCallback(&myHandler, cast(void*)context); extern(C) void myHandler(void* ctx) { // Assuming that the callback is invoked only once, the // added root can be removed again now to allow the GC // to collect it later. GC.removeRoot(ctx); GC.clrAttr(ctx, GC.BlkAttr.NO_MOVE); auto context = cast(Object)ctx; // Use context here… } - static nothrow @nogc void removeRoot(const void* p);
-
Удаляет блок памяти, на который указывает p, из внутреннего списка корней, которые будут сканироваться во время сбора. Если p равно null или не является значением, ранее переданным в addRoot(), то никакой операции не выполняется.
- Параметры:
void* pУказатель в блок памяти, управляемый сборщиком мусора, или null.
- static nothrow @nogc void addRange(const void* p, size_t sz, const TypeInfo ti = null);
-
Добавляет
p[0 .. sz]в список диапазонов памяти, которые будут сканироваться на наличие указателей во время сбора. Если p равно null, никакой операции не выполняется.Обратите внимание, что
p[0 .. sz]обрабатывается как непрозрачный диапазон памяти, предполагаемый в качестве надлежаще управляемого вызывающим методом. В частности, если p указывает во внутреннюю область блока памяти, управляемого сборщиком мусора, addRange не помечает этот блок как активный.- Параметры:
void* pУказатель на действительный адрес памяти или null. size_t szРазмер блока в байтах для добавления. Если sz равно нулю, то не будет выполнена никакая операция. Если p равно null, то sz должно быть равно нулю. TypeInfo tiTypeInfo для описания памяти. Сборщик мусора может использовать эту информацию для улучшения сканирования указателей или для вызова финализаторов.
- Пример
// Allocate a piece of memory on the C heap. enum size = 1_000; auto rawMemory = core.stdc.stdlib.malloc(size); // Add it as a GC range. GC.addRange(rawMemory, size); // Now, pointers to GC-managed memory stored in // rawMemory will be recognized on collection.
- static nothrow @nogc void removeRange(const void* p);
-
Удаляет диапазон памяти, начинающийся с p, из внутреннего списка диапазонов, которые будут сканироваться во время сбора. Если p равно null или не представляет значение, ранее переданное в addRange(), то никакой операции не выполняется.
- Параметры:
void* pУказатель на действительный адрес памяти или null.
- static void runFinalizers(scope const void[] segment);
-
-
Выполняет все финализаторы, находящиеся в диапазоне адресов данного сегмента кода. Это используется перед разгрузкой общих библиотек. Предполагается, что все соответствующие объекты, имеющие финализатор в этом сегменте кода, мертвы, использование их во время или после вызова этого метода имеет неопределённое поведение.
- Параметры:
void[] segmentдиапазон адресов сегмента кода.
- static nothrow @nogc @safe bool inFinalizer();
-
Запрашивает у СУУ, выполняет ли текущий поток финализацию объектов в рамках сбора мусора или явного вызова runFinalizers.
Так как некоторые реализации СУУ (например, текущая консервативная) не поддерживают выделение памяти СУУ во время финализации объектов, эта функция может использоваться для защиты от таких программистских ошибок.
- Возвращает:
- true, если текущий поток находится в финализаторе, деструктор, вызванный СУУ.
- Примеры:
-
// Only code called from a destructor is executed during finalization. assert(!GC.inFinalizer);
- Примеры:
-
enum Outcome { notCalled, calledManually, calledFromDruntime } static class Resource { static Outcome outcome; this() { outcome = Outcome.notCalled; } ~this() { if (GC.inFinalizer) { outcome = Outcome.calledFromDruntime; import core.exception : InvalidMemoryOperationError; try { /* * Presently, allocating GC memory during finalization * is forbidden and leads to * `InvalidMemoryOperationError` being thrown. * * `GC.inFinalizer` can be used to guard against * programming erros such as these and is also a more * efficient way to verify whether a destructor was * invoked by the GC. */ cast(void) GC.malloc(1); assert(false); } catch (InvalidMemoryOperationError e) { return; } assert(false); } else outcome = Outcome.calledManually; } } static void createGarbage() { auto r = new Resource; r = null; } assert(Resource.outcome == Outcome.notCalled); createGarbage(); GC.collect; assert( Resource.outcome == Outcome.notCalled || Resource.outcome == Outcome.calledFromDruntime); auto r = new Resource; GC.runFinalizers((cast(const void*)typeid(Resource).destructor)[0..1]); assert(Resource.outcome == Outcome.calledFromDruntime); Resource.outcome = Outcome.notCalled; debug(MEMSTOMP) {} else { // assume Resource data is still available r.destroy; assert(Resource.outcome == Outcome.notCalled); } r = new Resource; assert(Resource.outcome == Outcome.notCalled); r.destroy; assert(Resource.outcome == Outcome.calledManually);
- static nothrow ulong allocatedInCurrentThread();
-
Возвращает количество байтов, выделенных для текущего потока с момента запуска программы. Это то же самое, что GC.stats().allocatedInCurrentThread, но быстрее.
- Примеры:
- Использование allocatedInCurrentThread
ulong currentlyAllocated = GC.allocatedInCurrentThread(); struct DataStruct { long l1; long l2; long l3; long l4; } DataStruct* unused = new DataStruct; assert(GC.allocatedInCurrentThread() == currentlyAllocated + 32); assert(GC.stats().allocatedInCurrentThread == currentlyAllocated + 32);
-
- pure nothrow @nogc @trusted void* pureMalloc()(size_t size);
pure nothrow @nogc @trusted void* pureCalloc()(size_t nmemb, size_t size);
pure nothrow @nogc @system void* pureRealloc()(void* ptr, size_t size);
pure nothrow @nogc @system void pureFree()(void* ptr); -
Чистые варианты функций выделения памяти C
malloc,calloc, иreallocи функции освобождения памятиfree.UNIX 98 требует, чтобы errno было установлено в ENOMEM при ошибке. Чистота достигается сохранением и восстановлением значения
errno, таким образом, ведя себя так, как будто оно никогда не менялось.- См. также:
- Правила чистоты D, которые допускают выделение памяти в определенных обстоятельствах.
- Примеры:
-
ubyte[] fun(size_t n) pure { void* p = pureMalloc(n); p !is null || n == 0 || assert(0); scope(failure) p = pureRealloc(p, 0); p = pureRealloc(p, n *= 2); p !is null || n == 0 || assert(0); return cast(ubyte[]) p[0 .. n]; } auto buf = fun(100); assert(buf.length == 200); pureFree(buf.ptr);
- @system void __delete(T)(ref T x);
-
Уничтожает и затем освобождает объект.
Подробно,
__delete(x)возвращается без эффекта, еслиxявляетсяnull. В противном случае, она выполняет следующие действия последовательно:- Вызывает деструктор
~this()для объекта, на который ссылаетсяx(еслиxявляется ссылкой на класс или интерфейс) или для объекта, на который указываетx(еслиxявляется указателем наstruct). Массивы структур вызывают деструктор, если он определен, для каждого элемента в массиве. Если деструктор не определен, этот шаг не оказывает никакого эффекта. - Освобождает память, выделенную для
x. Еслиxявляется ссылкой на класс или интерфейс, память, выделенная для базового экземпляра, освобождается. Еслиxявляется указателем, память, выделенная для объекта, на который он указывает, освобождается. Еслиxявляется встроенным массивом, память, выделенная для массива, освобождается. Еслиxне ссылается на память, ранее выделенную с помощьюnew(или более низкоуровневых эквивалентов в API СУУ), поведение неопределённо. - Наконец,
xустанавливается вnull. Любая попытка чтения или записи освобождённой памяти через другие ссылки приведёт к неопределённому поведению.
- Примечание
- Пользователи должны отдавать предпочтение
destroyдля явной финализации объектов и прибегать кcore.memory._deleteтолько в тех случаях, когдаobject.destroyне представляется целесообразным.
- Параметры:
T xобъект агрегата, который должен быть уничтожен
- См. также:
-
destroy,core.GC.free
- История:
- Ключевое слово
deleteпозволяло освободить память, выделенную СУУ. Поскольку это по своей природе не@safe, оно было устаревшим. Эта функция была добавлена, чтобы обеспечить плавный переход отdelete. Она выполняет ту же функциональность, что и прежнее ключевое словоdelete.
- Примеры:
- Удаление классов
bool dtorCalled; class B { int test; ~this() { dtorCalled = true; } } B b = new B(); B a = b; b.test = 10; assert(GC.addrOf(cast(void*) b) != null); __delete(b); assert(b is null); assert(dtorCalled); assert(GC.addrOf(cast(void*) b) == null); // but be careful, a still points to it assert(a !is null); assert(GC.addrOf(cast(void*) a) == null); // but not a valid GC pointer
- Примеры:
- Удаление интерфейсов
bool dtorCalled; interface A { int quack(); } class B : A { int a; int quack() { a++; return a; } ~this() { dtorCalled = true; } } A a = new B(); a.quack(); assert(GC.addrOf(cast(void*) a) != null); __delete(a); assert(a is null); assert(dtorCalled); assert(GC.addrOf(cast(void*) a) == null);
- Примеры:
- Удаление структур
bool dtorCalled; struct A { string test; ~this() { dtorCalled = true; } } auto a = new A("foo"); assert(GC.addrOf(cast(void*) a) != null); __delete(a); assert(a is null); assert(dtorCalled); assert(GC.addrOf(cast(void*) a) == null);
- Примеры:
- Удаление массивов
int[] a = [1, 2, 3]; auto b = a; assert(GC.addrOf(b.ptr) != null); __delete(b); assert(b is null); assert(GC.addrOf(b.ptr) == null); // but be careful, a still points to it assert(a !is null); assert(GC.addrOf(a.ptr) == null); // but not a valid GC pointer
- Примеры:
- Удаление массивов структур
int dtorCalled; struct A { int a; ~this() { assert(dtorCalled == a); dtorCalled++; } } auto arr = [A(1), A(2), A(3)]; arr[0].a = 2; arr[1].a = 1; arr[2].a = 0; assert(GC.addrOf(arr.ptr) != null); __delete(arr); assert(dtorCalled == 3); assert(GC.addrOf(arr.ptr) == null);
- Вызывает деструктор
© 1999–2021 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/core_memory.html