2013-06-04 2 views
2

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

Q1: Определите утечки памяти в приведенном ниже коде на C++ и объясните, как их исправить. [9] знаков

#include <string> 

class Logger { 
    public: 
     static Logger &get_instance() { 
      static Logger *instance = NULL; 
      if (!instance){ 
       instance = new Logger(); 
      } 
      return *instance; 
     } 

     void log (std::string const &str){ 
      // ..log string 
     } 
    private: 
     Logger(){ 
     } 
     Logger(Logger const&) { 
     } 
     Logger& operator= (Logger const &) { 
     } 
     ~Logger() { 
     } 
}; 

int main(int argcv, char *argv[]){ 
    int *v1 = new int[10]; 
    int *v2 = new int[20]; 
    Logger::get_instance() . log ("Program Started"); 
    // .. do something 

    delete v1; 
    delete v2; 
    return 0; 
} 

Моего ответ, что если основные не заканчивает выполнение из-за досрочный возврат или исключение броска, что удаления никогда не будут работать в результате чего память никогда не будет освобождена. Я делаю чтение, и я считаю, что auto_ptr решит проблемы? Будет ли это так же просто, как смена строк? :

auto_ptr<int> v1 = new int[10]; 
auto_ptr<int> v2 = new int[20]; 

v1.release(); 
delete v1; 

Q2: Почему виртуальным членам требуется больше памяти, чем объекты класса без виртуальных членов?

A: Поскольку каждый виртуальный член требует, чтобы указатель также хранился в vtable, требующем больше места. Хотя это приравнивается к очень небольшому увеличению пространства.

ответ

1

Ваш первый ответ правильный, чтобы получить кредит, но то, что экзаменатор был, вероятно, ищет является освобождение из Logger *instance

В данном коде, памяти instance выделяется, но никогда не освобождаться.

Второй ответ выглядит хорошо.

+0

Привет, как я могу освободить экземпляр Logger? (Я знаю о бесплатном и все, что если malloc используется, но не уверен, как это было сделано в этом примере). Это не произойдет в конце основного, так как это все равно вызовет ту же проблему, что и я, изложенный выше, или нет? – user2092004

+0

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

+0

К счастью, это всего лишь объяснение, поэтому мне нужно только знать, что я буду делать. Поэтому, говоря, что память для экземпляра не освобождается и требует выделения. Благодаря! – user2092004

3

Q1: Обратите внимание, что v1 и v2 являются указателями int, которые ссылаются на массив из 10 и 20 соответственно. Удаления оператор не совпадает - то есть, так как массив, он должен быть

delete[] v1; 
delete[] v2; 

так, что весь массив освобождается. Помните, что всегда соответствие new[] and delete[] и new and delete

Я считаю, что вы уже правильно на Q2. Vtable и соответствующие указатели, которые необходимо отслеживать, увеличивают потребление памяти.

+0

ohh, прошлая статья определенно удаляет v1 и удаляет v2 без квадратных скобок! Тогда у кого-то должно быть что-то не так. – user2092004

+0

Хороший глаз! Я пропустил, что удаление не совпало –

1

экземпляр никогда не удаляется, и вы должны использовать оператор delete [] в main().

0

Q1:

несколько gotchyas -

  • одноплодной картина очень опасно, например, он не поточно, два потока могут прийти и создать два класса - вызывает утечку памяти, окружить EnterCriticalSection или какой-либо другой механизм синхронизации потоков и все еще небезопасен и не рекомендуется использовать.
  • singleton класс не освобождает память, singleton должен быть подсчитан, чтобы действительно действовать правильно.
  • вы используете статическую переменную внутри функции, что еще хуже, чем использование статического члена для класса.
    • вы выделяете с новым [] и удалить без удаления []

Я подозреваю, ваш вопрос две вещи: - Свободна одноточечно указатель - использование удалить []

В целом, однако, очистка процесса очистит оборванные вещи.

Q2:

вашего второй вопрос правильно, потому что виртуальные члены требуют виртуальных таблиц, что делает класс больше

2

Просто резюмировать:

  1. показанной программа имеет неопределенное поведение, используя неправильную форму удаления, поэтому говорить об утечках для исполнение несущественно

  2. , если предыдущий был зафиксирован, утечки Уолд приходят из:

    • новый Logger(); // всегда
    • два других новых использования, если последующие новые броски или строковые броски бросают или ... часть в бросках.
  3. для исправления v1 и v2 auto_ptr не является хорошим объявлением, которое вы выделили новым []. вы можете использовать boost :: auto_array или лучше сделать v array<int, 10> или не менее vector<int>. И вы абсолютно не используете release(), а затем вручную удаляете, но вставляете это в умный указатель.

  4. крепежный экземпляр интересный. То, что представлено, называется «негерметичным синглэном», которое должно утечка экземпляра. Но будьте вездесущими после создания, если что-то захочет использовать его во время выхода программы. Если это не предназначено, экземпляр не должен создаваться с использованием нового, но должен быть непосредственно, являющимся локальным статическим или статическим пространством имен.

  5. вопрос плохо сформулирован, сравнивая несовместимые вещи. Предполагая, что это дезинфицировано, ответ заключается в том, что a для класса с экземплярами виртуальных членов (очень вероятно) несут дополнительный указатель на VMT. Кроме того, сам VMT имеет одну запись для каждого виртуального члена после некоторых общих накладных расходов. Последнее действительно незначительно, но первое может быть проблемой, поскольку класс с 1 байтом состояния может забрать 8-байтовый указатель и, возможно, еще 7 байтов заполнения.

Смежные вопросы