
Создание собственных операторов new и delete
Как вы знаете, C++ позволяет вашим программам перегружать операторы. Аналогично вы можете перегрузить операторы new и delete, чтобы изменить их поведение. Например, предположим, что вы выделяете 100 байт памяти для хранения супер-секретных данных о вашей компании. Когда вы в дальнейшем освобождаете эту память с помощью оператораdelete, освобождается буфер, который содержал эту память, т.е. те самые 100 байт, содержащие супер-секретные данные о вашей компании. Предположим, корпоративный шпион (и программист) имеет доступ к вашему компьютеру, его программа теоретически может распределить тот же 100-байтный массив в памяти вашего компьютера и изучить ваши супер-секреты. Перегружая оператор delete, ваша программа может сначала заполнить этот буфер нулями или другими бессмысленными символами, а потом освободить эту память. Следующая программа MYDELETE.CPP перегружает оператор delete. Она сначала перезаписывает 100 байт, на которые указывает указатель, а затем освобождает память, используя для этого функцию библиотеки этапа выполнения free:
#include <iostream.h>
#include <stdlib.h>
#include <string.h>
static void operator delete(void *pointer)
{ char *data = (char *) pointer; int i; for (i = 0; i < 100; i++) data[i] = 0; cout << "Секрет в безопасности!" << endl; free(pointer); }
void main(void)
{ char *pointer = new char[100]; strcpy(pointer, "Секреты моей компании"); delete pointer; }
При запуске программа выделяет память для строкового массива с помощью оператора new. Затем она копирует секреты компании в эту строку. В дальнейшем программа использует перегруженный операторdelete для освобождения памяти. Внутри функции delete приведенный ниже оператор присваивает значение переменной pointer указателю на символьную строку:
char *data = (char *) pointer;
Символы (char *), которые называются оператором приведения типов,предназначены только для того, чтобы сообщить компилятору C++, что функция знает, что она присваивает указатель типа void (см. выше параметры функции) указателю типа char. Если вы опустите оператор приведения типов, программа не откомпилируется. Затем функция копирует нули в 100 байт буфера и освобождает память, используя для этого функцию библиотеки этапа выполнения free. Очень важно отметить, что эта функция (оператор delete) работает только с областью памяти размером 100 байт. Поскольку данная программа выделяет память только один раз, она работает корректно. Если вы измените программу таким образом, чтобы выделялось только десять байт памяти и не сделаете подобных изменений в этой функции, то она перезапишет 90 байт памяти, которые ваша программа, возможно, использовала для других целей, приведя к ошибке. Однако, используя функции библиотеки этапа выполнения, ваши программы могут получить больше информации о размере области памяти, на которую указывает определенный указатель.
Подобным образом следующая программа NEW_OVER.CPP перегружает оператор C++ new. В данном случае перегруженная функция помещает символьную строку "Учимся программировать на языке C++!" в начало выделяемой памяти:
#include <iostream.h>
#include <alloc.h>
#include <string.h>
static void *operator new(size_t size)
{ char *pointer; pointer = (char *) malloc(size); if (size > strlen( "Учимся программировать на языке C++!")) strcpy(pointer, "Учимся программировать на языке C++!"); return(pointer); }
void main(void)
{ char *str = new char[100]; cout << str << endl; }
Как видите, функция new использует для выделения памяти функциюmalloc библиотеки этапа выполнения. Если размер выделяемой памяти достаточен для хранения строки "Учимся программировать на языке C++!", данная функция использует функцию strcpy библиотеки этапа выполнения для копирования строки в область памяти.