Язык программирования C++ для профессионалов


Свободная память - часть 2


char* save_string(const char* p) { char* s = new char[strlen(p)+1]; strcpy(s,p); return s; }

Отметим, что для перераспределения памяти, отведенной операцией new, операция delete должна уметь определять размер размещенного объекта. Например:

int main(int argc, char* argv[]) { if (argc < 2) exit(1); char* p = save_string(arg[1]); delete[] p; }

Чтобы добиться этого, приходится под объект, размещаемый стандартной операцией new, отводить немного больше памяти, чем под статический (обычно, больше на одно слово). Простой оператор delete уничтожает отдельные объекты, а операция delete[] используется для уничтожения массивов.

Операции со свободной памятью реализуются функциями:

void* operator new(size_t); void operator delete(void*);

Здесь size_t - беззнаковый целочисленный тип, определенный в <stddef.h>.

Стандартная реализация функции operator new() не инициализирует предоставляемую память.

Что случится, когда операция new не сможет больше найти свободной памяти для размещения? Поскольку даже виртуальная память небесконечна, такое время от времени происходит. Так, запрос вида:

char* p = new char [100000000];

обычно не проходит нормально. Когда операция new не может выполнить запрос, она вызывает функцию, которая была задана как параметр при обращении к функции set_new_handler() из <new.h>. Например, в следующей программе:

#include <iostream.h> #include <new.h> #include <stdlib.h>

void out_of_store() { cerr << "operator new failed: out of store\n"; exit(1); }

int main() { set_new_handler(&out_of_store); char* p = new char[100000000]; cout << "done, p = " << long(p) << '\n'; }

скорее всего, будет напечатано не "done", а сообщение:

operator new failed: out of store // операция new не прошла: нет памяти

С помощью функции new_handler можно сделать нечто более сложное, чем просто завершить программу. Если известен алгоритм операций new и delete (например, потому, что пользователь определил свои функции operator new и operator delete), то обработчик new_handler может попытаться найти свободную память для new. Другими словами, пользователь может написать свой "сборщик мусора", тем самым сделав вызов операции delete необязательным. Однако такая задача, безусловно, не под силу новичку.

По традиции операция new просто возвращает указатель 0, если не удалось найти достаточно свободной памяти. Реакция же на это new_handler не была установлена. Например, следующая программа:

#include <stream.h>

main() { char* p = new char[100000000]; cout << "done, p = " << long(p) << '\n'; }

выдаст

done, p = 0

Память не выделена, и вам сделано предупреждение! Отметим, что, задав реакцию на такую ситуацию в функции new_handler, пользователь берет на себя проверку: исчерпана ли свободная память. Она должна выполняться при каждом обращении в программе к new (если только пользователь не определил собственные функции для размещения объектов пользовательских типов).




Начало  Назад  Вперед



Книжный магазин