Russian Qt Forum

Qt => Общие вопросы => Тема начата: 8Observer8 от Февраль 12, 2014, 18:41



Название: Причины утечки памяти и способы борьбы с ними
Отправлено: 8Observer8 от Февраль 12, 2014, 18:41
Привет!

Как я понял, один из самых действенных способов борьбы с утечками памяти - это использование "умных указателей"

Вот примеры из этой книги: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html (http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html)

Код:
void leaky()
{
    Simple* mySimplePtr = new Simple();  // BUG! Memory is never released!
    mySimplePtr->go();
}

Код:
void notLeaky()
{
    shared_ptr<Simple> mySimpleSmartPtr(new Simple());
    mySimpleSmartPtr->go();
}

В первом примере утечка, а во втором - нет (память после выхода из функции notLeaky() сразу освобождается)

А вот в следующем примере утечка памяти:

Код:
void couldBeLeaky()
{
    Simple* mySimplePtr = new Simple();
    mySimplePtr->go();
    delete mySimplePtr;
}

Так как при вызове mySimplePtr->go(); может срабатывать исключение, тогда строка кода: delete mySimplePtr; не будет выполняться.

Нужно ли в Qt везде, где используются указатели использовать shared_ptr?

К примеру, здесь:

Код:
Dialog *w = new Dialog();


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Serr500 от Февраль 12, 2014, 18:57
Как я понял, один из самых действенных способов борьбы с утечками памяти - это использование "умных указателей"
Один из самых действенных способов борьбы с утечками памяти - использование Java, C# или другого языка с автоматической сборкой мусора!  ;) А в C++ самый действенный способ - писать безглючный код. Надо помнить, что исключение - это исключительная ситуация и не злоупотреблять ими.

Вот примеры из этой книги: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html (http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html)
Ну и фигню же Вы читаете! Да ещё и на английском...

Нужно ли в Qt везде, где используются указатели использовать shared_ptr?

К примеру, здесь:

Код:
Dialog *w = new Dialog();
А Вы подумайте.  ;) Подсказка: Qt::WA_DeleteOnClose.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: 8Observer8 от Февраль 12, 2014, 19:09
А в C++ самый действенный способ - писать безглючный код. Надо помнить, что исключение - это исключительная ситуация и не злоупотреблять ими.

Не понял. Мешьше использовать исключения? А как же ошибки обрабатывать?

Если даже полностью отказаться от использования исключений, то это же нас не спасает. Так как многие функции STL могут их выбрасывать. Это я по поводу того что: "не злоупотреблять ими"

Вот примеры из этой книги: http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html (http://www.wrox.com/WileyCDA/WroxTitle/Professional-C-2nd-Edition.productCd-0470932449.html)
Ну и фигню же Вы читаете! Да ещё и на английском...

Я ничего лучше не нашёл. Посоветуете что-нибудь?

Нужно ли в Qt везде, где используются указатели использовать shared_ptr?

К примеру, здесь:

Код:
Dialog *w = new Dialog();
А Вы подумайте.  ;) Подсказка: Qt::WA_DeleteOnClose.

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


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Bepec от Февраль 12, 2014, 19:20
В Qt присутствует ответственность родителей за детей. Т.е. задавая объекту родителя, вы можете быть уверены что он позаботиться об его удалении при своём удалении.

Самый просто способ в С++ бороться с утечками уже был озвучен - писать безглючный код. Использование sharedPtr конечно хорошо, но...
У меня уже рефлекс - я выделил память, надо освободить. И shared проверить :D


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Serr500 от Февраль 12, 2014, 19:37
Не понял. Мешьше использовать исключения? А как же ошибки обрабатывать?

Если даже полностью отказаться от использования исключений, то это же нас не спасает. Так как многие функции STL могут их выбрасывать. Это я по поводу того что: "не злоупотреблять ими"
Я для себя вывел такую формулу работы: обрабатывать только те исключения, которые могут возникнуть в коде, который я не контролирую, а сам генерирую исключения только в коде, который предназначен для использования другими людьми и только в том случае, когда без этого обойтись уже нельзя (ну, или в техзадании жёстко прописано). В подавляющем большинстве случаев исключений можно избежать, скрупулёзно выполняя все проверки и передавая каким-либо образом признак ошибки вызвавшему коду. Если мой код выбрасывает исключение, то он уже не может справиться с ошибкой и почти всегда в этом случае приложение проще убить, чем пытаться что-то исправить. Если Вы пишете свой код, то его правильное написание не вызовет исключения. Если же приходится использовать внешние библиотеки, "любящие" исключения, то даже в этом случае можно обойтись без их обработки, поскольку условия возникновения исключений часто точно известны. Например, стопроцентная гарантия от out_of_range - проверка индекса перед вызовом метода.

Я ничего лучше не нашёл. Посоветуете что-нибудь?
Мнэ-э-э... Вспомню - напишу.

Я где-то встречал информацию, что объекты, которые наследуют от QObject не нужно удалять. Как Вы это понимаете?
Это не совсем верно. Точнее, совсем не верно. Нужно, но можно обойтись автоматическим удалением. Например, если объект имеет родителя, то родитель удалит всех детей при своём разрушении. Но если объект родителя не имеет, то нужно грохнуть его самостоятельно.

А вот Вам головоломка. Что будет в следующем коде и почему?
Код:
class QObject2 : public QObject {
    public:
        void work() {
            // Что-то делаем
            deleteLater();
        }
}

// В одной далёкой-далёкой функции...
{
    std::shared_ptr<QObject> Ptr(new QObject2);
    Ptr->work();
    QApplication::processEvents();
}


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 12, 2014, 19:42
В Qt присутствует ответственность родителей за детей. Т.е. задавая объекту родителя, вы можете быть уверены что он позаботиться об его удалении при своём удалении.
Тут главное не забывать, что удаление произойдет только при удалении родителя, а многие родители живут все время работы программы.
И получается так: объекты создаются, им присваивается "вечный" родитель и все эти объекты живут все время, хотя никому не нужны.
Можно вспомнить объекты QNetworkReply, которые создаются объектом QNetworkAccessManager.

Самый просто способ в С++ бороться с утечками уже был озвучен - писать безглючный код.
Да, это самый простой способ, но лучший способ это писать идеальный код. Плохо, что это практически невозможно. :)

У меня уже рефлекс - я выделил память, надо освободить.
А если указатель на объект нужно передать в "свободное плаванье"?
А с shared_ptr таких проблем нет совсем.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Bepec от Февраль 12, 2014, 21:37
Ну если в плаванье, то там перекладываю ответственность на капитана того корабля :D
С Shared нужно тоже учитывать свои нюансы.

Хотя мб у меня это сложилось из-за библиотеки с которой приходилось их использовать. Просто для запуска приложению нужно было держать 8 умных указателей, а при создании объекта ещё по 3 (1 на объект, 1 на нотификатор, 1 на сокет). В результате получался код % на 15 из указателей.

Да и созданные под это классы были уже "неизвлекаемые" из системы. А со свободными указателями гораздо проще :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 12, 2014, 22:51
Ну если в плаванье, то там перекладываю ответственность на капитана того корабля :D
Так если капитан того корабля вы сами? Начинаете придумывать костыли и потому при изменении условий переделывать... и так может продолжаться постоянно.
С умными указателями ничего переделывать не приходится.

С Shared нужно тоже учитывать свои нюансы.
Например.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 12, 2014, 23:22
Нужно ли в Qt везде, где используются указатели использовать shared_ptr?
Скажу про себя. Во всех своих программах я использую исключительно умные указатели (обычных указателей нет вообще).
Но это не распространяется на программы с использованием Qt. Связано это с тем, что у Qt есть свой "стиль" написания кода и мне приходится его придерживаться, что бы с моим кодом могли работать все те, кто уже работает с Qt. В нем, конечно, есть умные указатели, но не в тех объемах как хотелось бы. :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: OKTA от Февраль 12, 2014, 23:27
А вот Вам головоломка. Что будет в следующем коде и почему?
Код:
class QObject2 : public QObject {
    public:
        void work() {
            // Что-то делаем
            deleteLater();
        }
}

// В одной далёкой-далёкой функции...
{
    std::shared_ptr<QObject> Ptr(new QObject2);
    Ptr->work();
    QApplication::processEvents();
}

Объект не удалится, потому что deleteLater не вызовется из очереди через ProcessEvents?
А за счет shared_ptr удаление произойдет все равно в итоге.
Я так понимаю.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Igors от Февраль 13, 2014, 06:03
А вот Вам головоломка. Что будет в следующем коде и почему?
Код:
class QObject2 : public QObject {
    public:
        void work() {
            // Что-то делаем
            deleteLater();
        }
}

// В одной далёкой-далёкой функции...
{
    std::shared_ptr<QObject> Ptr(new QObject2);
    Ptr->work();
    QApplication::processEvents();
}

Объект не удалится, потому что deleteLater не вызовется из очереди через ProcessEvents?
А за счет shared_ptr удаление произойдет все равно в итоге.
Я так понимаю.
Того же мнения - deleteLater остается в очереди (кстати хз почему). А когда shared_ptr удалит объект - деструктор QObject вычистит deleteLater из очереди (как и все event'ы посланные ему). Итого - все корректно. И здесь лучше использовать QPointer, тогда хоть тот, хоть этот удалит - голова не болит.

Как я понял, один из самых действенных способов борьбы с утечками памяти - это использование "умных указателей"
Вы ищите "простые" решения для совсем не простых вещей, что в принципе неверно. Да, на простых примерах "умные указатели" выглядят очень привлекательно, но реально это не всегда так. См хотя бы пример выше - зачем мы ввязались в головоломку, была ли в этом реальная необходимость? Не решаем ли мы проблемы что сами себе и создали привлекая умные/могучие средства? Лучше начать с базовых средств языка, и только если возникнет необходимость - кого-то привлечь.

И еще: отладка с "умными указателями" существенно замедляется - часто именно по этой причине я обхожусь простецким delete


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: deMax от Февраль 13, 2014, 11:55
А в C++ самый действенный способ - писать безглючный код.

Самый простой способ это - CTRL+F, искать по всему проекту "new". И проследить, что все что создано, корректно удаляется(Это не займет очень много времени). Библиотеки проверить тестами - если они текут то подумать как снизить протечку. Для наследников QObject надо смотреть где удаляется родитель и стоит ли заранее удалить объект в нужном месте или пусть его родитель вместе с собой удалит.

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

Еще есть valgrid и тесты.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: 8Observer8 от Февраль 14, 2014, 12:25
Всем большое спасибо за ответы! Я позже разберу их.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Akon от Февраль 15, 2014, 13:23
Цитировать
Скажу про себя. Во всех своих программах я использую исключительно умные указатели (обычных указателей нет вообще).
Но это не распространяется на программы с использованием Qt. Связано это с тем, что у Qt есть свой "стиль" написания кода и мне приходится его придерживаться, что бы с моим кодом могли работать все те, кто уже работает с Qt. В нем, конечно, есть умные указатели, но не в тех объемах как хотелось бы.
Old, допустим ты пишешь библиотеку, в которой есть функция:
Код:
NonQObject* createObject()
{
    NonQObject* result = new NonQObject;
    functionThatCanThrowException();  // может сделать, throw std::runtime_error(), например
    return result;
}

Как ты будешь писать эту функцию?


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 15, 2014, 13:44
Old, допустим ты пишешь библиотеку, в которой есть функция:

Код
C++ (Qt)
QSharedPointer<NonQObject> createObject()
{
   QSharedPointer<NonQObject> result( new NonQObject );
   functionThatCanThrowException();  // может сделать, throw std::runtime_error(), например
   return result;
}
 

Если без Qt, то будет shared_ptr.
Как я уже писал выше, в проектах без Qt у меня все без исключения указатели умные.

ADD: практически для всех указателей я стараюсь делать typedef:
Код
C++ (Qt)
typedef QSharedPointer<NonQObject> NonObjectPtr;
 
NonQObjectPtr createObject()
{
   NonQObjectPtr result( new NonQObject );
   functionThatCanThrowException();  // может сделать, throw std::runtime_error(), например
   return result;
}
 


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Bepec от Февраль 15, 2014, 16:55
оффтоп: и потом образуется по привычке
typedef int fint;
typedef std::string textstring;
typedef bool variable;

PS проекты после этого нечитабельные на 200% :D

PPS хотел добавить пример такого кода, но вспомнил что подписывал бумажку :/


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Akon от Февраль 15, 2014, 18:53
Old: Спасибо. Типичная реализация, удобная для автора либы, но может оказаться неудобной для пользователя, поскольку навязывается смарт-поинтер.

Код:
NonQObject* createObject()
{
    NonQObject* result = new NonQObject;
    try {
        functionThatCanThrowException();  // может сделать, throw std::runtime_error(), например
    }
    catch(....) {
        delete result;
        throw;
    }
    return result;
}

void foo()
{
    QScopedPointer<NonQObject> localObject = createObject();
    // do something
}
В функции foo для локального объекта вы вынуждены были бы использовать QSharedPointer, что избыточно/снижает читабельность кода.




Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 15, 2014, 18:57
но может оказаться неудобной для пользователя, поскольку навязывается смарт-поинтер.
Не навязывает. Просто все поинтеры в программе должны быть смарт. :) Они для этого и сделаны.

В функции foo для локального объекта вы вынуждены были бы использовать QSharedPointer, что избыточно/снижает читабельность кода.
Это не избыточно и тем более не снижает читабельность. Но это как я уже написал, если все поинтеры в программе смарт. А к этому нужно стремиться и по возможности использовать.

А вот ваш костылец заметно длинней и такие чудеса нужно вставлять везде, где может возникнуть исключение. Вот она избыточность и нечитаемость. :)

И это только создание объекта, а если мы проследим все костыли и исправления в программе, что бы его корректно удалять, то лишних строк будет еще больше. А с shared_ptr ничего менять не придется.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Igors от Февраль 15, 2014, 19:16
А вот ваш костылец заметно длинней и такие чудеса нужно вставлять везде, где может возникнуть исключение. Вот она избыточность и нечитаемость. :)
Я гораздо чаще действую как Akon и "костылем" это не считаю - ведь и Вам придется потратиться на обработку исключения, только в др, месте. И как Вы туда подадите данные исключения/восстановления - хз. А тут все под рукой.

А вот такой вопросик. Есть много "shared", но мне часто нужно знать не просто "удален или нет" а "кто его держит" - есть ли такая возможность?. А в Qt не знаю даже как посмотреть "а сколько ссылок"  :'(


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 15, 2014, 19:29
Я гораздо чаще действую как Akon и "костылем" это не считаю
Вы знаете, а я не удивлен.

ведь и Вам придется потратиться на обработку исключения, только в др, месте. И как Вы туда подадите данные исключения/восстановления - хз. А тут все под рукой.
Вы код Akon не поняли? Он здесь только удаляет указатель, а на обработку он потратится в другом месте, где не все под рукой. :)

А вот такой вопросик. Есть много "shared", но мне часто нужно знать не просто "удален или нет" а "кто его держит" - есть ли такая возможность?
Так вы пишите программу, вы должны знать тот единственный объект, который является владельцем данных. Все остальные только пользователи.

А в Qt не знаю даже как посмотреть "а сколько ссылок"  :'(
Зачем вам эта бесполезная информация?


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Igors от Февраль 15, 2014, 20:20
Вы код Akon не поняли? Он здесь только удаляет указатель, а на обработку он потратится в другом месте, где не все под рукой. :)
Необязательно, часто можно и не испускать вторичное а вернуть NULL. Да и пример слишком прост - если понадобится напр установить флаг/переменную (хоть код ошибки), то лучше сделать это по месту и потом вторичное throw типа "на свободу с чистой совестью".

Так вы пишите программу, вы должны знать тот единственный объект, который является владельцем данных. Все остальные только пользователи.
Ну допустим и так (не суть), вот смотрю - ресурс жив, а я рассчитывал на его удаление/выгрузку. Вероятно др объект его держит, но вот какой? А у вумного указателя ничего для этого нет, счетчик ссылок - и то не везде


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 15, 2014, 20:28
Необязательно, часто можно и не испускать вторичное а вернуть NULL.
Это вы дальше с Akon уже обсуждайте. ;)

вот смотрю - ресурс жив, а я рассчитывал на его удаление/выгрузку.
Где смотрите, в отладчике?

Вероятно др объект его держит, но вот какой?
Вы хотите, что бы умный указатель еще и всех клиентов сохранял? Не можете разобраться со своими объектами - используйте логи или  набросайте свой вариант  умного указателя (или враппер для него), что бы он сохранял всех клиентов. И пользуйтесь им для отладки.
Или вы хотели бы что бы он в боевом коде всех сохранял?


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Akon от Февраль 15, 2014, 21:43
Цитировать
Не навязывает. Просто все поинтеры в программе должны быть смарт.  Они для этого и сделаны.
Я согласен, что когда все поинтеры в вашей программе смарт и программа задумана под это - это хорошо. Не навязывает - это значит смарт поинтера просто нет, и пользователь сам решит: использовать голый указатель или тут же обернуть его своим смартом. Рассмотрите такой пример:
Код:
QList<QSharedPointer<NonQObject> >
В данном случае sizeof(QSharedPointer<NonQObject>) > sizeof(void*), что вызовет инстанцирование QList с менее эффективной реализацией по сравнению с голым указателем. Вы автор библиотеки и не знаете, как будет использоваться объект. Фактически, вы навязали QSharedPointer и менее эффективный QList, последнее запросто может не понравиться пользователю.

Цитировать
Это не избыточно и тем более не снижает читабельность.
Ну как вам сказать... тогда зачем scoped pointer нужен вообще?

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

Цитировать
И это только создание объекта, а если мы проследим все костыли и исправления в программе, что бы его корректно удалять, то лишних строк будет еще больше. А с shared_ptr ничего менять не придется.
Я не говорю, что дальше должен использоваться голый указатель. Моя мысль, иллюстрированная примером, следующая: если на стыке (библиотека - программа) интерфейс в смартах, то это может быть не всегда удобно! Мне просто было интересно ваше мнение.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 15, 2014, 22:14
если на стыке (библиотека - программа) интерфейс в смартах, то это может быть не всегда удобно! Мне просто было интересно ваше мнение.
Мое мнение, что смарты нужно запихивать везде и в библиотеки в первую очередь, что бы заставлять ими пользоваться. :)
Я уверен, что большинство их противников просто никогда не имели с ними дела (или имели в тестовых примерчиках), и не очень представляют что это такое.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: kambala от Февраль 15, 2014, 22:27
2Old: можешь посоветовать хороший материал по умным указателям? максимум, что я использовал — это QPointer.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 15, 2014, 22:50
2Old: можешь посоветовать хороший материал по умным указателям? максимум, что я использовал — это QPointer.
К сожалению ничего фундаментального посоветовать не могу, давно я не интересовался этим вопросом.
Поэтому, с удовольствием пообщаюсь по этому вопросу и расскажу свое видение использования этих удобных инструментов. :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Akon от Февраль 15, 2014, 23:01
Old: Я не противник смартов, наоборот. Мне просто хотелось иметь дискуссию и в более глубоком русле, и сос своей стороны я показал, что смарты в некоторых аспектах не безупречны.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 15, 2014, 23:05
Old: Я не противник смартов, наоборот. Мне просто хотелось иметь дискуссию и в более глубоком русле, и сос своей стороны я показал, что смарты в некоторых аспектах не безупречны.
Как и все у нас. ;)
Идеальных контейнеров тоже не существует и мы вынуждены все время выбирать чем пожертвовать что бы что-то получить. Все имеет свою цены и смарты в том числе.
И для меня они дают значительно больше, чем забирают. )


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: kambala от Февраль 15, 2014, 23:06
2Old: можешь посоветовать хороший материал по умным указателям? максимум, что я использовал — это QPointer.
К сожалению ничего фундаментального посоветовать не могу, давно я не интересовался этим вопросом.
Поэтому, с удовольствием пообщаюсь по этому вопросу и расскажу свое видение использования этих удобных инструментов. :)
так может уж лучше тогда тему-статью-туториал? ;) думаю не мне одному будет интересно.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Akon от Февраль 15, 2014, 23:10
Имхо, необходимость использовать смарты должна придти из опыта - если бы не было распространенных реализаций, вы бы сделали свою. Для глубокого изучения чешите сорцы.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 00:00
так может уж лучше тогда тему-статью-туториал? ;) думаю не мне одному будет интересно.
Вот не умею я нормально писать. Давайте лучше это обсуждать в этой теме, например.
На самом деле, начать ими пользоваться очень легко с запуском нового проекта: просто берете и начинаете везде вместо обычных указателей использовать shared_ptr (не допуская циклических ссылок). :)

Писал, писал... какая то фигня получается... :) Лучше будем обсуждать конкретные моменты. :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 00:18
если бы не было распространенных реализаций, вы бы сделали свою.
Так и делал... :) В середине 90-х, шаблонов у меня в компиляторе еще не было (BC 3.1), и в каждый класс, у которого хотелось иметь такой функционал, подмешивал класс со счетчиком и методами attach/detach. :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Igors от Февраль 16, 2014, 11:10
Или вы хотели бы что бы он в боевом коде всех сохранял?
И это тоже бы хотел. Пример: N разнотипных объектов использует шареный ресурс, напр картинку. Все хорошо, как только все N будут удалены - и ресурс будет удален/выгружен. Но вот пользователь выбрал из меню "отключить картинки" - что делать? Как мне найти всех пользователей ресурса и сказать им "освобождай"?

А так да - экономит delete, удобно отдать в асинхронный вызов, и.т.п. с этим никто не спорит. Но каких-то больших результатов от "умности указателей" ожидать не стоит.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 11:22
Но вот пользователь выбрал из меню "отключить картинки" - что делать? Как мне найти всех пользователей ресурса и сказать им "освобождай"?
Вы пытаетесь навязать дополнительный функционал указателю, который никак не связанный с его задачами. Вы часто пытетесь объединять разные задачи в одной сущности. Из этого никогда ничего хорошего не получиться.

А так да - экономит delete, удобно отдать в асинхронный вызов, и.т.п. с этим никто не спорит.
Это одни из простейшитх задач, которые он ришает.

Но каких-то больших результатов от "умности указателей" ожидать не стоит.
Так никто и не ждет. Это просто указатель. :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Akon от Февраль 16, 2014, 11:44
Цитировать
И это тоже бы хотел. Пример: N разнотипных объектов использует шареный ресурс, напр картинку. Все хорошо, как только все N будут удалены - и ресурс будет удален/выгружен. Но вот пользователь выбрал из меню "отключить картинки" - что делать? Как мне найти всех пользователей ресурса и сказать им "освобождай"?
Это действительно никак не связано с смартами. Используйте контейнер со смартами под каждый ресурс. Отключили картинки - очистили контейнер.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Igors от Февраль 16, 2014, 12:55
Вы пытаетесь навязать дополнительный функционал указателю, который никак не связанный с его задачами.
Это действительно никак не связано с смартами.
Но ведь только что (пока не было этого противного требования "отключить" извне) все прекрасно вписывалось - завел в каждом классе умный указатель, и все! Только вот
Цитировать
этот редиска на первом скачке расколется
И придется возвращаться к тем самым attach/detach  :)

Используйте контейнер со смартами под каждый ресурс. Отключили картинки - очистили контейнер.
Не понял, если можно - подробнее. Напр как тогда рулить с точки зрения одного объекта (клиента)?


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Johnik от Февраль 16, 2014, 14:08
Пример: N разнотипных объектов использует шареный ресурс, напр картинку. Все хорошо, как только все N будут удалены - и ресурс будет удален/выгружен. Но вот пользователь выбрал из меню "отключить картинки" - что делать? Как мне найти всех пользователей ресурса и сказать им "освобождай"?
Использовать текучие указатели в паре с умными.



Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Bepec от Февраль 16, 2014, 14:47
Умные указатели иногда выгодно использовать в "стандартных" реализациях. В остальных случаях лучше простые. Соединить две разные библиотеки, построенные на умных и простых указателях можно, но необходимо досконально знать и ту и ту библиотеку.

Это инструмент. Можно использовать эффективно и в нужной программе, а можно "микроскопом гвозди забивать".


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 14:48
Но ведь только что (пока не было этого противного требования "отключить" извне) все прекрасно вписывалось - завел в каждом классе умный указатель, и все!
Конечно вписывалось, от него требовалось владеть объектом - он с этим прекрасно справлялся. Вы захотели, что бы он еще что-то помнил, но увы, без дополнительных телодвижений он  этого не сможет, не закладывали в него этих способностей изначально (слава Богу).
Также он не сможет загружать контент с сайта, считать логарифмы и сохранять свое состояние в базу данных. Но он превосходно справится со своей непосредственной задачей.

Не понял, если можно - подробнее. Напр как тогда рулить с точки зрения одного объекта (клиента)?
Посылайте сигнал/event всем объекта, при получении которого они забудут ресурс. Как только они все это сделают, ресурс разрушится.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 15:19
В остальных случаях лучше простые.
Тут нужно уточнять, кому лучше. Вам? Ну хорошо. Для меня простые указатели хуже. :)

Это инструмент. Можно использовать эффективно и в нужной программе, а можно "микроскопом гвозди забивать".
Это обычный указатель, не нужно его использовать в "нужной программе". Он хорош во всех программах. :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Bepec от Февраль 16, 2014, 15:27
Я привёл пример - попробуйте скрестить библиотеку с простыми указателями и библиотеку с умными. И не простую динамическую dll, а полноценную библиотеку с взаимодействием.

PS это хорошо когда все и вся использует умные. Если что-то использует простые, вся схема рушится :D


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 15:34
PS это хорошо когда все и вся использует умные. Если что-то использует простые, вся схема рушится :D
Я выше это писал.
Если библиотека действительно ценна для проекта, то ее интерфейс закрывается фасадом с умными указателями и дальше все гармонично взаимодействует. А вот если вам лень это делать и обычные указатели из этой библиотеки лезут во все места проекта, то... наверное этот проект не очень важен или у вас много свободного времени на отслеживание всех этих указателей. :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Igors от Февраль 16, 2014, 16:41
Конечно вписывалось, от него требовалось владеть объектом - он с этим прекрасно справлялся. Вы захотели, что бы он еще что-то помнил, но увы, без дополнительных телодвижений он  этого не сможет, не закладывали в него этих способностей изначально (слава Богу).
Также он не сможет загружать контент с сайта, считать логарифмы и сохранять свое состояние в базу данных. Но он превосходно справится со своей непосредственной задачей.
Так я же и не возражаю, а просто привожу пример как "умность" оказывается очень короткой. И таких примеров много

Посылайте сигнал/event всем объекта, при получении которого они забудут ресурс. Как только они все это сделают, ресурс разрушится.
А каким "всем"? Откуда я их возьму/узнаю? И что послать? Нужно делать какой-то интерфейс понимаемый многими объектами  :'( Да и в событийной схеме это проблемно.

Что мне не нравится во всех этих "умных" - что они берут на себя удаление. Схема "умный ресурс" гораздо мощнее, он также может удалить себя если нет клиентов, но + многое другое. А на стороне клиента возможности очень бедные.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 16:49
просто привожу пример как "умность" оказывается очень короткой. И таких примеров много
Да, я выше писал, они контент с сайта получать не умеют, сохранять свои состояния в базе данных тоже, даже логарифм посчитать не могут. И кто назвал их умными?

А каким "всем"? Откуда я их возьму/узнаю?
А вы их храните где-то. Вы только что хотели, что бы их хранили указатели, они не могут... значит их придется хранить вам.

Да и в событийной схеме это проблемно.
В событийной схеме послать событие проблемно? Что то вы с ней не то делаете.

Схема "умный ресурс" гораздо мощнее, он также может удалить себя если нет клиентов, но + многое другое. А на стороне клиента возможности очень бедные.
Ну так умный указатель это маленький винтик, с помощью которого легко сделать "умный ресурс" и даже "очень умный ресурс".


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Igors от Февраль 16, 2014, 17:22
А вы их храните где-то. Вы только что хотели, что бы их хранили указатели, они не могут... значит их придется хранить вам.
Придется - так придется. Но у меня одно число указателей, а у каждого "умника" свое число ссылок, нехорошо, не по уму иметь 2 копии данных.

В событийной схеме послать событие проблемно? Что то вы с ней не то делаете.
Послать-то без проблем, но никто не обещал что в очереди не появится событие которое опять вызовет захват того же ресурса.

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


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: Old от Февраль 16, 2014, 17:33
Но у меня одно число указателей, а у каждого "умника" свое число ссылок, нехорошо, не по уму иметь 2 копии данных.
Здесь не понял: "одно число указателей", "свое число ссылок". Давайте от объектов исходить.

Послать-то без проблем, но никто не обещал что в очереди не появится событие которое опять вызовет захват того же ресурса.
Ну так как его можно освобождать, если его кто-то постоянно хочет? Вначале нужно эту "хотелку" вразумить.

Это интересно обсудить, может создадим тему?
Такие темы на форуме поднимались, причем именно в контексте умных указателей: http://www.prog.org.ru/topic_16093_0.html
Если интересно, давайте обсудим.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: 8Observer8 от Май 25, 2014, 21:04
У моего приложения в меню есть пункт "Settings". При нажатии на него появляется диалоговое окно. Будет ли это утечка памяти? Я где-то слышал, что объекты унаследованные от Object не надо уничтожать с помощью delete, так ли это? Где об этом написано?

Код
C++ (Qt)
void MainWindow::on_actionSettings_triggered()
{
   Settings *dialog = new Settings;
   dialog->setModal( true );
   dialog->show( );
}
 

Заранее спасибо за помощь.


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: gil9red от Май 25, 2014, 21:38
У моего приложения в меню есть пункт "Settings". При нажатии на него появляется диалоговое окно. Будет ли это утечка памяти? Я где-то слышал, что объекты унаследованные от Object не надо уничтожать с помощью delete, так ли это? Где об этом написано?

Код
C++ (Qt)
void MainWindow::on_actionSettings_triggered()
{
   Settings *dialog = new Settings;
   dialog->setModal( true );
   dialog->show( );
}
 

Заранее спасибо за помощь.


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

Код
C++ (Qt)
void MainWindow::on_actionSettings_triggered()
{
   MyDialog dialog;
   dialog.setWindowTitle( tr( "Settings" ) );
   if ( dialog.exec() == QDialog::Accepted )
      qDebug() << "Диалог завершился хорошо!";
}
 

http://qt-project.org/doc/qt-4.8/qdialog.html в разделе Code Examples хорошо показано как лучше всего использовать диалоги :)


Название: Re: Причины утечки памяти и способы борьбы с ними
Отправлено: 8Observer8 от Май 25, 2014, 22:19
То что надо! Спасибо! :)