ПроблемаОтсутствующая перегрузка функции выделения или удаления возникает, когда вы перегружаете operator new
но не перегружайте соответствующий operator delete
, или наоборот.
РискОбычно вы перегружаете operator new
для выполнения некоторой бухгалтерии в дополнение к выделению памяти в свободном хранилище. Если вы не перегрузите соответствующий operator delete
Вероятно, вы опускали некоторую соответствующую бухгалтерию при снятии памяти.
Дефект может также указывать на ошибку кодирования. Например, вы перегрузили форму размещения operator new[]
:
void *operator new[](std::size_t count, void *ptr);
но непостановочная форма
operator delete[]
:
void operator delete[](void *ptr);
вместо формы размещения:
void operator delete[](void *ptr, void *p );
ЗафиксироватьПри перегрузке operator new
, убедитесь, что вы перегрузите соответствующий operator delete
в тех же возможностях и наоборот.
Например, в классе, если вы перегрузите форму размещения operator new
:
class MyClass {
void* operator new ( std::size_t count, void* ptr ){
//...
}
};
Убедитесь, что вы также перегрузите форму размещения
operator delete
:
class MyClass {
void operator delete ( void* ptr, void* place ){
...
}
};
Как найти operator delete
соответствующий operator new
, см. страницы с описанием для operator new
и operator delete
.
Пример - Несоответствие между перегруженными operator new
и operator delete
#include <new>
#include <cstdlib>
int global_store;
void update_bookkeeping(void *allocated_ptr, bool alloc) {
if(alloc)
global_store++;
else
global_store--;
}
void *operator new(std::size_t size, const std::nothrow_t& tag);
void *operator new(std::size_t size, const std::nothrow_t& tag) {
void *ptr = (void*)malloc(size);
if (ptr != nullptr)
update_bookkeeping(ptr, true);
return ptr;
}
void operator delete[](void *ptr, const std::nothrow_t& tag);
void operator delete[](void* ptr, const std::nothrow_t& tag) {
update_bookkeeping(ptr, false);
free(ptr);
}
В этом примере операторы operator new
и operator delete[]
перегружены, но нет перегрузок соответствующих operator delete
и operator new[]
операторы.
Перегрузка operator new
вызывает функцию update_bookkeeping
для изменения значения глобальной переменной global_store
. Если значение по умолчанию operator delete
вызывается, эта глобальная переменная не затронута, что может бросить вызов ожиданиям разработчика.
Коррекция - перегрузка правильной формы operator delete
Если вы хотите перегрузить operator new
, перегрузить соответствующую форму operator delete
в тех же возможностях.
#include <new>
#include <cstdlib>
int global_store;
void update_bookkeeping(void *allocated_ptr, bool alloc) {
if(alloc)
global_store++;
else
global_store--;
}
void *operator new(std::size_t size, const std::nothrow_t& tag);
void *operator new(std::size_t size, const std::nothrow_t& tag) {
void *ptr = (void*)malloc(size);
if (ptr != nullptr)
update_bookkeeping(ptr, true);
return ptr;
}
void operator delete(void *ptr, const std::nothrow_t& tag);
void operator delete(void* ptr, const std::nothrow_t& tag) {
update_bookkeeping(ptr, false);
free(ptr);
}