Как действительно гарантируют, что при написании самого кода C++ это не вызовет утечек памяти?

В браузерах кроме IE необходимо использовать маленький объект флэш-памяти управлять буфером обмена, например,

6
задан Nathan Fellman 20 August 2009 в 13:48
поделиться

13 ответов

Используйте идиому RAII везде, где можете

Используйте интеллектуальные указатели, например std :: auto_ptr, где это необходимо. (не используйте auto_prt ни в одной из стандартных коллекций, так как это не будет работать так, как вы думаете)

25
ответ дан 8 December 2019 в 02:02
поделиться

По возможности избегайте создания объектов динамически. Программисты, пришедшие из Java и других подобных языков, часто пишут такие вещи, как:

string * s = new string( "hello world" );

, когда они должны были написать:

string s = "hello world";

Точно так же они создают коллекции указателей, когда они должны создавать коллекции значений. Например, если у вас есть такой класс:

class Person {
   public:
      Person( const string & name ) : mName( name ) {}
      ...
   private:
      string mName;
};

Вместо того, чтобы писать код вроде:

vector <Person *> vp;

или даже:

vector <shared_ptr <Person> > vp;

, вместо этого используйте значения:

vector <Person> vp;

Вы можете легко добавить к такому вектору:

vp.push_back( Person( "neil butterworth" ) );

и все память как для Person, так и для вектора управляется за вас. Конечно, если вам нужен набор полиморфных типов, вы должны использовать (умные) указатели

14
ответ дан 8 December 2019 в 02:02
поделиться
  1. Использовать RAII
  2. Скрыть параметры копирования по умолчанию, оператор = () в КАЖДОМ КЛАССЕ, если а) ваш класс тривиален и использует только собственные типы, и ВЫ ЗНАЕТЕ ВСЕГДА БУДЕТ ТАК б) ты явно определите свой собственный

В 1) RAII, идея состоит в том, чтобы удаление происходило автоматически, если вы поймете, что думаете: «Я только что позвонил по новому, мне нужно не забыть где-то вызвать delete», тогда вы делаете что-то не так . Удаление должно быть а) автоматическим или б) помещаться в dtor (и какой dtor должен быть очевиден).

On 2) Скрытие значений по умолчанию. Выявление недобросовестных копий по умолчанию и т. Д. Может быть кошмаром, проще всего избежать их, скрывая их. Если у вас есть общий «корневой» объект, от которого все наследуется (может быть удобно для отладки / профилирования в любом случае), здесь скрываются значения по умолчанию, тогда, когда что-то пытается назначить / скопировать наследующий класс, компилятор отключает, потому что ctor и т. Д. Не доступно в базовом классе.

5
ответ дан 8 December 2019 в 02:02
поделиться

Минимизируйте вызовы new, используя контейнеры STL для хранения ваших данных.

4
ответ дан 8 December 2019 в 02:02
поделиться

Основные шаги делятся на два:

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

Во-вторых, убедитесь, что вы никогда не перезаписываете указатель. Вы можете сделать это, используя класс интеллектуальных указателей вместо необработанных указателей, но если вы действительно убедитесь, что никогда не используете его с неявным преобразованием. (пример: используя библиотеку MSXML, я создал интеллектуальный указатель CCOMPtr для хранения узлов, чтобы получить узел, который вы вызываете методом get_Node, передавая адрес интеллектуального указателя, у которого был оператор преобразования, который возвращал базовый тип указателя. К сожалению , это означало, что, если интеллектуальный указатель уже содержал данные, данные этого элемента будут перезаписаны, что приведет к утечке предыдущего узла).

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

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

1
ответ дан 8 December 2019 в 02:02
поделиться

Я всегда использую std :: auto_ptr , когда мне нужно создать новый объект в куче.

std::auto_ptr<Foo> CreateFoo()
{
   return std::auto_ptr<Foo>(new Foo());
}

Даже если вы вызовете

CreateFoo()

, утечки не произойдет.

1
ответ дан 8 December 2019 в 02:02
поделиться

Two simple rules of thumb:

  • Never call delete explicitly (outside a RAII class, that is). Every memory allocation should be the responsibility of a RAII class which calls delete in the destructor.
  • Almost never call new explicitly. If you do, you should immediately wrap the resulting pointer in a smart pointer, which takes ownership of the allocation, and works as above.

In your own RAII classes, two common pitfalls are:

  • Failure to handle copying correctly: Who takes ownership of the memory if the object is copied? Do they create a new allocation? Do you implement both copy constructor and assignment operator? Does the latter handle self assignment?
  • Failure to consider exception safety. What happens if an exception is thrown during an operation (an assignment, for example)? Does the object revert to a consistent state? (it should always do this, no matter what) Does it roll back to the state it had before the operation? (it should do this when possible) std::vector has to handle this, during push_back for example. It might cause the vector to resize, which means 1) a memory allocation which may throw, and 2) all the existing elements have to be copied, each of which may throw. An algorithm like std::sort has to deal with it too. It has to call a user-supplied comparer, which could potentially throw too! if that happens, is the sequence left in a valid state? Are temporary objects destructed cleanly?

If you handle the above two cases in your RAII classes, it is pretty much impossible for them to leak memory. И если вы используете классы RAII для обертывания всех выделений ресурсов (выделения памяти, дескрипторы файлов, подключения к базе данных и любые другие типы ресурсов, которые должны быть получены и освобождены), тогда ваше приложение не сможет утечки памяти.

1
ответ дан 8 December 2019 в 02:02
поделиться

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

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

0
ответ дан 8 December 2019 в 02:02
поделиться

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

0
ответ дан 8 December 2019 в 02:02
поделиться

Существуют инструменты статического анализа кода, которые делают подобные вещи; Википедия - хорошее место для начала поиска. По сути, помимо осторожности и выбора правильных контейнеров, вы не можете дать никаких гарантий относительно написанного вами кода - отсюда и необходимость в таких инструментах, как valgrind и gdb.

0
ответ дан 8 December 2019 в 02:02
поделиться

Incorporate valgrind unit and system testing early in your development cycle and use it consistantly.

0
ответ дан 8 December 2019 в 02:02
поделиться

I'm with Glen and jalf regarding RAII at every opportunity.

IMHO you should aim to write completely delete-free code. The only explicit "delete"s should be in your smart pointer class implementations. If you find yourself wanting to write a "delete", go and find an appropriate smart pointer type instead. If none of the "industry standard" ones (boost's etc) fit and you find yourself wanting to write some bizzare new one, chances are your architecture is broken or at the least there will be maintenance difficulties in future.

I've long held that explicit "delete" is to memory management what "goto" is to flow control. More on this in this answer.

3
ответ дан 8 December 2019 в 02:02
поделиться
Другие вопросы по тегам:

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