Наиболее распространенные ошибки утечки памяти / ресурсов - PullRequest
5 голосов
/ 26 августа 2009

Все хорошие программисты на C ++ знают, как избежать утечки памяти (или таких ресурсов, как сокеты):

  1. Всегда используйте умные указатели, т.е. е .: std::auto_ptr, boost::shared_ptr.
  2. Всегда помните о праве собственности на объект: кто владеет, кто ссылается, кто несет ответственность и т. Д.

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

Я начинаю:

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

Ответы [ 5 ]

5 голосов
/ 26 августа 2009

Существует гораздо больше типов ошибок, чем просто утечки. В порядке от худшего к лучшему:

Повреждение памяти.

Данные хранятся в области, где они не должны. Это приводит к тому, что большинство проблем безопасности и гораздо сложнее отследить.

  • Повреждение "Случайное местоположение"
    • Данные хранятся в ячейке памяти, которую пользователь может контролировать.
    • Данные хранятся в массиве без проверки индексов.
    • Объект типа, производного от X, сохраняется в элементе массива, зарезервированном для базового типа X, а размер X больше размера его основания.
  • Пожизненная коррупция
    • Данные сохраняются в ячейке памяти после освобождения.
    • Используется неверный метод освобождения (несоответствие, в результате которого new / free, malloc / delete)
    • delete или free вызывается дважды по одному и тому же указателю.

Ошибка освобождения памяти

Память, которая больше не используется программой, остается выделенной.

  • Используется неверный метод освобождения: несоответствие приводит к new[] / delete вместо new[] / delete[].
  • Память не освобождается автоматически из-за циклической ссылки в схеме подсчета ссылок, что может произойти, если smart_ptr используется в циклической структуре данных, не обращая внимания на использование weak_ptr для кольцевой ссылки.
  • Память не освобождена из-за потерянного указателя - последний указатель на память был очищен перед вызовом free, поэтому нет возможности освободить его.
  • Память не освобождается из-за неправильной идентификации, когда содержащиеся в ней данные больше не нужны. Например, статический кеш, используемый для какой-то временной задачи, никогда не очищается.
2 голосов
/ 26 августа 2009
  • Вызов виртуальной функции, такой как «очистка», из деструктора базового класса. Вы, вероятно, делаете это только один раз ... (больше нет полиморфизма в деструкторе базового класса)
  • Не очищать stl :: multimap (не стирать, а только вставлять) и удивляться, почему ваша программа продолжает замедляться.
2 голосов
/ 26 августа 2009

Циркулярные ссылки распространены, и они не решаются std::auto_ptr или boost::shared_ptr В вашем списке нет замены (2), которая использует ваш мозг.

1 голос
/ 26 августа 2009

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

class A { 
public:
    int avery_useful_calculation()const { return 4; } 
private:
    // class shouldn't be instantiated as an automatic variable (on stack)
    virtual ~A(){} 
};

// client code: needs a very useful calculation

int i = (new A)->avery_useful_calculation();
0 голосов
/ 26 августа 2009

Может быть, я вне области, но у меня были странные ошибки при попытке "удалить" неинициализированные указатели.

Чтобы «избежать» утечки памяти, я использую структуру try {} __finally {}, если она реализована (но я где-то читал, что это может быть неэффективно, если исключение было вызвано во вспомогательном вызове)

...