Перехват исключений в конструкторе - PullRequest
5 голосов
/ 10 октября 2011

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

#include <exception>

class MyClass {

public:
       MyClass() 
       {
           c = new char[5];
           throw std::runtime_error("test");
       }

      ~MyClass ()
       {
           delete[] c;
       }

private:
    char *c;
};

int main()
{
    try 
    {
        MyClass Obj;

    } 
    catch (std::runtime_error)
    {

    }
}

Ответы [ 4 ]

6 голосов
/ 10 октября 2011

Перехватите исключение в конструкторе, приведите в порядок (освободите вашу память), а затем выбросите исключение без утечки памяти.

5 голосов
/ 10 октября 2011

Вам лучше использовать RAII , умный указатель в этом случае будет конкретным.

Или, альтернативно, Вы можете использовать стратегию Двухэтапное построение .

Вы всегда можете использовать блоки try-catch внутри тела конструктора и явно вызыватьудаляя все те ресурсы, которые вы динамически распределили, но подумайте о сценарии, в котором у вас есть n количество ресурсов, которые динамически распределяются, становится очень грязно явно отслеживать каждый ресурс, который вам нужно освободить в catch, вВ таком сценарии RAII предоставляет вам наилучшее решение, потому что тогда каждый ресурс неявно заботится о своем освобождении, и вам не нужны дополнительные ресурсы для отслеживания каждого ресурса.

boost::scoped_ptr или std::tr1::scoped_ptr подходят для этого сценария вместо необработанных указателей.

4 голосов
/ 10 октября 2011

Одним из способов является throw условное исключение в начале конструктора, а затем выделение памяти.

  MyClass() 
  {
     if(<condition>)
       throw std::runtime_error("test");
     c = new char[<SIZE>];
  }

Другой способ - использование специального синтаксиса try-catch(), заключающего конструктор:

MyClass() 
  try {
    c = new char[5];
    throw std::runtime_error("test");;
  }
  catch(std::runtime_error e) {
    delete[] c;
  }

Демо .

1 голос
/ 10 октября 2011

Вы можете перехватить исключение в теле конструктора, выполнить необходимую очистку, а затем сбросить исключение с помощью throw;

Тем не менее, исключения и ручная обработка памяти не сочетаются друг с другом. Вам будет гораздо лучше использовать объект, который автоматически управляет памятью члена c (например, std::string, std::vector<char>, std::unique_ptr<char[]> и т. Д.). Вам действительно нужно явно управлять памятью, только если вы пишете класс, подобный одному из вышеперечисленных, целью которого является именно забота об этой памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...