предотвращение утечки памяти (в зависимости от конкретного случая) - PullRequest
3 голосов
/ 21 июня 2010

Рассмотрим следующую ситуацию:

SomeType *sptr = someFunction();
// do sth with sptr

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

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

Как мне избежать этого?

EDIT:

Ссылки более безопасны, чем указатели. Будет ли вызываться деструктор для SomeType, если я сделаю:

{
  SomeType &sref = *sptr;
}

Любые идеи.

Ответы [ 6 ]

19 голосов
/ 21 июня 2010

Вам необходимо прочитать документацию по someFunction.someFunction необходимо четко определить владельца возвращаемого указателя (владеет ли он вызывающим абонентом и должен ли он вызвать delete или someFunction владеет им и будет гарантировать, что объект будет уничтожен в будущем).

Если код не документирует его поведение, безопасного способа его использовать нет.

3 голосов
/ 21 июня 2010

Что вы подразумеваете под уходом?Завершить процесс?Ваша куча обычно уничтожается, когда процесс уничтожается.Вы можете получить утечку только после выхода из процесса, если ваша операционная система попросит вас что-то сделать (например, получить файл или дескриптор окна) и не освободит ее.

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

Если документация функции не говорит вам, что делать, проверьте документацию библиотеки - иногда целая библиотека использует одну и ту же политику, а не документирует ее в каждой функции.Если вы не можете найти ответ где-либо, свяжитесь с автором или отказаться от библиотеки, поскольку вероятность ошибок не стоит, ИМХО.

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

0 голосов
/ 22 июня 2010

Как отмечают другие, это зависит от функции, чтобы обеспечить свои предположения о праве собственности в коде.Вот один из способов сделать это, используя так называемые умные указатели :

#include <iostream>
#include <boost/shared_ptr.hpp>

struct Foo
{ 
  Foo( int _x ) : x(_x) {}
  ~Foo() { std::cout << "Destructing a Foo with x=" << std::hex << x << "\n"; }
  int x;
};

typedef boost::shared_ptr<Foo> FooHandle;

FooHandle makeFoo(int _x = 0xDEADBEEF) {
    return FooHandle(new Foo(_x));
}

int main()
{
    {
        FooHandle fh = makeFoo();
    }
    std::cout<<"No memory leaks here!\n";

    return 0;
}
0 голосов
/ 21 июня 2010

Если someFunction возвращает объект для меня, было бы нормально иметь парную функцию, такую ​​как someFunctionFree, которую вы будете вызывать для освобождения ресурсов объекта SomeType.Все необходимые вещи должны быть найдены в документации someFunction (в основном как объект может быть освобожден или если объект автоматически освобожден).Я лично предпочитаю соответствующую функцию освобождения (пара CreateObject / DestroyObject).

0 голосов
/ 21 июня 2010

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

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

0 голосов
/ 21 июня 2010

Это всегда хорошая привычка убирать за собой, не думайте, что ОС сделает это;

Есть хорошее изменение - ваша IDE или отладчик сообщат об утечке памяти при выходе из приложения.

Что ты должен делать? Ну, это зависит, но обычно вам нужно освободить память, выделенную someFunction (), и документация, вероятно, поможет вам в этом, либо есть API для освобождения памяти, либо вам нужно сделать это вручную, бесплатно или удалить.

Макс

...