Кто удаляет память, выделенную во время “новой” операции, которая имеет исключение в конструкторе?

Самая простая веб-программа является сценарием CGI, который является в основном просто программой, стандартный вывод которой перенаправляется к веб-браузеру, выполняющему запрос. В этом подходе каждая страница имеет свой собственный исполняемый файл, который должен быть загружен и проанализирован по каждому запросу. Это делает действительно простым разбудить что-то и выполнение, но масштабируется плохо и с точки зрения производительности и с точки зрения организации. Таким образом, когда мне нужна очень динамическая страница очень быстро, которая не превратится в большую систему, я использую сценарий CGI.

Каждый повышается от этого, встраивает Ваш код Python в Ваш код HTML, такой как с PSP. Я не думаю, что многие люди используют это в наше время, так как современные шаблонные системы сделали это довольно устаревшим. Я работал с PSP некоторое время и нашел, что он имел в основном те же организационные пределы как сценарии CGI (каждая страница имеет свой собственный файл) плюс некоторые связанные с пробелом раздражения от попытки смешать неосведомленный пробелу HTML с чувствительным к пробелу Python.

следующие повышаются, очень простые веб-платформы, такие как web.py, который я также использовал. Как сценарии CGI, очень просто разбудить что-то и выполнение, и Вам не нужны никакая сложная конфигурация или автоматически сгенерированный код. Ваш собственный код будет довольно прост понять, таким образом, Вы будете видеть то, что происходит. Однако это не столь многофункционально как другие веб-платформы; в прошлый раз я использовал его, не было никакого отслеживания сессии, таким образом, я должен был прокрутить свое собственное. Это также имеет "слишком много волшебного поведения", чтобы заключить Guido в кавычки ("upvars (), вот еще").

Наконец, у Вас есть многофункциональные веб-платформы, такие как Django. Они потребуют, чтобы немного работы стало простым Привет Мировая работа программ, но каждый главный имеет большое, правильно написанное учебное руководство (особенно Django) для обхода Вас через него. Я настоятельно рекомендую использование одной из этих веб-платформ для любого реального проекта из-за удобства и функций и документации, и т.д.

В конечном счете необходимо будет решить то, что Вы предпочитаете. Например, платформы все шаблонные языки использования (специальный код/теги) для генерации файлов HTML. Некоторые из них, такие как шаблоны Гепарда позволяют Вам записать произвольный код Python так, чтобы можно было сделать что-либо в шаблоне. Другие, такие как шаблоны Django более строги и вынуждают Вас разделить свой код представления от Вашей логики программы. Это - все о том, что Вы лично предпочитаете.

Другим примером является обработка URL; некоторые платформы, такие как Django сделали, чтобы Вы определили URL в своем приложении через регулярные выражения. Другие, такие как CherryPy автоматически отображают Ваши функции на URL Вашими именами функций. Снова, это - персональное предпочтение.

я лично использую соединение веб-платформ при помощи CherryPy для моего материала веб-сервера (параметры формы, обработка сессии, отображение URL, и т.д.) и Django для моего объектно-реляционного отображения и шаблонов. Моя рекомендация состоит в том, чтобы запуститься с веб-платформы высокого уровня, проложить себе путь через ее учебное руководство, затем запуститься на маленьком персональном проекте. Я сделал это со всеми технологиями, которые я упомянул, и это было действительно выгодно. В конечном счете Вы получите ощущение того, что Вы предпочитаете и становитесь лучшим веб-программистом (и лучшим программистом в целом) в процессе.

49
задан Jason Plank 29 November 2011 в 02:10
поделиться

7 ответов

Вы должны ответить на аналогичные вопросы здесь и здесь . Обычно, если конструктор генерирует исключение, вы можете быть уверены, что память самого объекта снова будет освобождена. Хотя, если во время конструктора была запрошена другая память, вы можете освободить ее перед выходом из конструктора с исключением.

На ваш вопрос, ВОЗ удаляет память, ответ - это код, стоящий за оператором new (который генерируется компилятором). Если он распознает исключение, покидающее конструктор, он должен вызвать все деструкторы членов классов (поскольку они уже были успешно созданы до вызова кода конструктора) и освободить их память (может быть выполнено рекурсивно вместе с вызовом деструктора, наиболее вероятно вызывая для них правильное удаление ), а также освобождает память, выделенную для самого этого класса. Конечно, может быть еще много работы, но я не могу вытащить из головы все детали, потому что они зависят от реализации каждого компилятора.

38
ответ дан 7 November 2019 в 11:50
поделиться

Если Конструктор выбрасывает выделенную для объекта память, она автоматически возвращается в систему.

Обратите внимание, что деструктор сгенерированного класса не будет вызываться.
Но деструктор любого базового класса (где базовый конструктор завершен) также будет вызван.

Примечание:
Как отметило большинство других людей, члены могут нуждаться в некоторой очистке.

Члены, которые были полностью инициализированы, будут иметь свои деструкторы, но если у вас есть какие-либо элементы указателя RAW, которыми вы владеете (то есть удалите в деструкторе), вам придется сделайте некоторую очистку, прежде чем выполнять бросок (еще одна причина не использовать собственные указатели RAW в вашем классе).

#include <iostream>

class Base
{
    public:
        Base()  {std::cout << "Create  Base\n";}
        ~Base() {std::cout << "Destroy Base\n";}
};

class Deriv: public Base
{
    public:
        Deriv(int x)    {std::cout << "Create  Deriv\n";if (x > 0) throw int(x);}
        ~Deriv()        {std::cout << "Destroy Deriv\n";}
};

int main()
{
    try
    {
        {
            Deriv       d0(0);  // All constructors/Destructors called.
        }
        {
            Deriv       d1(1);  // Base constructor and destructor called.
                                // Derived constructor called (not destructor)
        }
    }
    catch(...)
    {
        throw;
        // Also note here.
        // If an exception escapes main it is implementation defined
        // whether the stack is unwound. By catching in main() you force
        // the stack to unwind to this point. If you can't handle re-throw
        // so the system exception handling can provide the appropriate
        // error handling (such as user messages).
    }
}
6
ответ дан 7 November 2019 в 11:50
поделиться

Из стандарта C ++ 2003 5.3.4 / 17 - Новое:

Если какая-либо часть описанной выше инициализации объекта завершается выдачей исключения и подходящим освобождением Функция освобождения памяти вызывается для освобождения памяти, в которой создавался объект, после чего исключение продолжает распространяться в контексте нового выражения. Если не удается найти однозначно совпадающую функцию освобождения памяти, распространение исключения не приводит к освобождению памяти объекта. [Запись: Это подходит, когда вызываемая функция распределения не выделяет память; в противном случае это может привести к утечке памяти. ]

Таким образом, утечка может быть, а может и не быть - это зависит от того, удастся ли найти подходящий освободитель (что обычно бывает, если только оператор new / delete не был переопределен). В случае, когда есть подходящий освободитель, компилятор отвечает за соединение при вызове его, если конструктор выдает ошибку.

Обратите внимание, что это более или менее не связано с тем, что происходит с ресурсами, полученными в конструкторе, что я обсуждал в первой попытке ответа - и вопрос, который обсуждается во многих часто задаваемых вопросах, статьях и публикациях.

6
ответ дан 7 November 2019 в 11:50
поделиться

Если объект не может завершить уничтожение из-за того, что конструктор выдает исключение, первое, что должно произойти (это происходит как часть специальной обработки конструктора), - это уничтожить все создаваемые переменные-члены. - если исключение выбрасывается в списке инициализаторов, это означает, что уничтожаются только те элементы, для которых инициализатор завершил работу.

Затем, если объект был выделен с помощью new , соответствующая функция освобождения ( operator delete ) вызывается с теми же дополнительными аргументами, которые были переданы в operator new . Например, new (std :: nothrow) SomethingThatThrows () выделит память с помощью оператора new (size_of_ob, nothrow) , попытайтесь построить SomethingThatThrows , уничтожьте все элементы, которые были успешно созданы, затем вызовите operator delete (ptr_to_obj, nothrow) при распространении исключения - это не приведет к утечке памяти.

Вы должны быть осторожны при выделении нескольких объектов в последовательность - если один из последующих бросает, предыдущие не будут автоматически освобождены. Наилучший способ решить эту проблему - использовать интеллектуальные указатели, поскольку их деструкторы как локальные объекты будут вызываться во время раскрутки стека, и их деструкторы будут правильно освобождать память.

предыдущие не удаляются автоматически. Наилучший способ решить эту проблему - использовать интеллектуальные указатели, поскольку их деструкторы как локальные объекты будут вызываться во время раскрутки стека, и их деструкторы будут правильно освобождать память.

предыдущие не удаляются автоматически. Наилучший способ решить эту проблему - использовать интеллектуальные указатели, поскольку их деструкторы как локальные объекты будут вызываться во время раскрутки стека, и их деструкторы будут правильно освобождать память.

26
ответ дан 7 November 2019 в 11:50
поделиться

Я думаю, что конструктор может вызывать исключение как-то странно. Не могли бы вы получить возвращаемое значение и протестировать его в своем основном файле?

class Blah
{
   public:

   Blah()
       {
           if Error
           {
              this.Error = "oops";
           }
        }
};

void main()
{
Blah* b = NULL;

b = new Blah();

if (b.Error == "oops")
{
   delete (b);
   b = NULL;
}
-6
ответ дан 7 November 2019 в 11:50
поделиться

Цитата из FAQ по C ++ ( parashift.com ):

[17.4] Как мне обрабатывать ресурсы, если мои конструкторы могут бросать исключения?

Каждый элемент данных внутри вашего объекта должен убирать свой беспорядок.

Если конструктор выдает исключение, деструктор объекта не запустить. Если ваш объект уже сделал что-то, что нужно отменить (например, выделение некоторой памяти, открытие файла или блокировка семафор), этот «материал, который нужно отменить» необходимо запомнить элементом данных внутри объекта.

Например, вместо выделения памяти в необработанные Fred * данные элемент, поместите выделенную память в объект-член "умного указателя", и деструктор этого умного указателя удалит Fred объект, когда умный указатель умирает. Шаблон std :: auto_ptr является пример такой как "умный указатель". Вы также можете написать свой интеллектуальный указатель подсчета ссылок . Вы также можете использовать интеллектуальные указатели для "указания" на записи на диске или объекты на других машинах .

Кстати, если вы думаете, что ваш класс Fred будет выделен в умный указатель, будьте вежливы со своими пользователями и создайте typedef в вашем классе Fred :

  #include 

 class Fred {
 общественность:
 typedef std :: auto_ptr  Ptr;
 ...
 };

Этот typedef упрощает синтаксис всего кода, который использует ваш объекты: ваши пользователи могут сказать Fred :: Ptr вместо std :: auto_ptr :

  #include "Fred.h"

void f (std :: auto_ptr  p); // явно, но многословно
void f (Fred :: Ptr p); // проще

 void g ()
 {
std :: auto_ptr  p1 (новый Fred ()); // явно, но многословно
Фред :: Ptr p2 (новый Фред ()); // проще
 ...
 }
-1
ответ дан 7 November 2019 в 11:50
поделиться

Короче говоря, если вы не выполнили какие-либо распределения других сущностей в своем объекте (как в вашем примере), то выделенная память будет автоматически удалена. Однако любые новые операторы (или что-либо еще, что напрямую управляет памятью) должны обрабатываться в операторе catch в конструкторе. В противном случае объект удаляется без удаления его последующих выделений, и у вас, мой друг, возникает утечка.

2
ответ дан 7 November 2019 в 11:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: