Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Setner от Октябрь 01, 2012, 15:32



Название: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Setner от Октябрь 01, 2012, 15:32
Здравствуйте, я новичок здесь.

Прочитал книгу Шлее, но так и не понял, как правильно работать с Qt, чтобы не было утечек памяти. Долго искал какую нибудь библиотеку или макрос, как в VC++ 2010, чтобы банально проверить, вдруг что то потекло, но так и не смог найти.

Сейчас я понимаю следующее:

Чтобы не заботиться об удалении объекта, нужно сделать класс этого объекта наследником QObject. Это не совсем нормально по моему мнению, так как где то я могу банально забыть наследоваться, и компилятор мне ничего не скажет, а память потечёт.

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

В связи с этим у меня к вам просьбы:


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

т.е

class MyClass( ... наследуетесь от QObject/QWidget?...
{

   //Какой указатель на ресурс динамической памяти используете - простой или умный?
   ...

}.

MyClass::MyClass(
   //Присвоение указателю начального значения, если нужно
...
)

void MyClass::UsePointer(
   //Присвоение указателю какого либо значения
...
)

MyClass::~MyClass(
   //Как удаляете и удаляете ли вообще?
...
)


int main(argc, argv)
{

   //Как создаёте объект класса, вызываете метод UsePointer?

   return 0;
}

2. Как всё-таки контроллировать утечки памяти? Есть ли какие то встроенные макросы как в VC++2010? Может, какие то утилиты?



Заранее очень очень благодарю!


Название: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: mutineer от Октябрь 01, 2012, 15:35
0) Создай отдельную тему
1) QWidget представляет собой виджет, рисуемый на форме, QObject - объект с сигналами, слотами и некоторыми другими няшками из Qt. Макрос нужен только если нужны сигналы, слоты, проперти и т.д. в классе
2) Очень сильно зависит от обстоятельств.

А чтобы объект удалился автоматически мало просто отнаследовать его от QObject, надо еще ему родителя задать


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igors от Октябрь 01, 2012, 16:11
На Вындоуз я пока на MSVC 2008, поэтому интересно что там за макрос такой в 2010 который Вы упоминаете?

Вопрос звучит несколько наивно, т.к. возможность утечек в самой природе языка, как бы плата за эффективность кода, это нормально. Способ решить эту проблему "раз и навсегда" мне неизвестен. В общем случае - "я распределил, я и удаляю". Есть неск исключений, наиболее популярное "родитель удаляет детей". Отлов утечек производится инструментами - на каждой платформе своими, к Qt это отношения не имеет.

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

Книги, Шлее и др. может и неплохи, но практического опыта не заменят


Название: Re: как правильно работать с Qt, чтобы не было ут&#
Отправлено: Setner от Октябрь 01, 2012, 16:52
0) Создай отдельную тему
1) QWidget представляет собой виджет, рисуемый на форме, QObject - объект с сигналами, слотами и некоторыми другими няшками из Qt. Макрос нужен только если нужны сигналы, слоты, проперти и т.д. в классе
2) Очень сильно зависит от обстоятельств.

Спасибо! Извиняюсь за редактирование своего поста.

Есть ли в Qt аналогичные исследования производительности различных указателей ( *, QSharedPointer и QWeakPointer) как в http://habrahabr.ru/post/138550/ (http://habrahabr.ru/post/138550/)? Т. е. стоит ли ограничивать использование умных указателей на критичных участках кода?

А чтобы объект удалился автоматически мало просто отнаследовать его от QObject, надо еще ему родителя задать

А как в Qt проверяют, что объект действительно удалён? Только через дебаггер?


На Вындоуз я пока на MSVC 2008, поэтому интересно что там за макрос такой в 2010 который Вы упоминаете?

я пользовался
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
хочется хотя бы что то типа этого в Qt
можно написать что то своё, но просто я думал уже давно что то подобное встроено в Кьют.


Отлов утечек производится инструментами - на каждой платформе своими, к Qt это отношения не имеет.

То есть надо компилировать прогу и прогонять её под сторонним отладчиком или использовать в коде стороннюю библиотеку (например duma)?


Ещё раз благодарю всех за помощь.



Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: mutineer от Октябрь 01, 2012, 16:55
А как в Qt проверяют, что объект действительно удалён? Только через дебаггер?

Так же, как и просто в С++ - например засовыванием вывода в консоль в деструктор объекта


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Setner от Октябрь 01, 2012, 16:58
А как в Qt проверяют, что объект действительно удалён? Только через дебаггер?

Так же, как и просто в С++ - например засовыванием вывода в консоль в деструктор объекта

Хм, то есть пишем свои костыли. Понятно. Благодарю!


Название: Re: как правильно работать с Qt, чтобы не было ут&#
Отправлено: Igors от Октябрь 01, 2012, 18:34
А как в Qt проверяют, что объект действительно удалён? Только через дебаггер?
...
я пользовался
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
хочется хотя бы что то типа этого в Qt
можно написать что то своё, но просто я думал уже давно что то подобное встроено в Кьют.

То есть надо компилировать прогу и прогонять её под сторонним отладчиком или использовать в коде стороннюю библиотеку (например duma)?
Qt - это framework, поэтому все правила С++, компилятора и платформы столь же применимы. Т.е. спокойно используете тот же CrtSetDbgFlag, те же методы отлова что и без всякого Qt. Если в языке нет возможности проверить валидность указателя - то ее не будет и в Qt.

Если человек знает и любит C/C++, то изучение Qt будет легким и приятным. И наоборот  :)


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: navrocky от Октябрь 01, 2012, 19:08
Ну под винду же полно инструментов для отлова ошибок при работе с памятью:

1) какое-то убожество встроено в студию
2) aqtime
3) devpartner

и еще масса менее известных..
Кажется от intel что-то есть.

Под линуксом - valgrind.

Цитировать
Долго искал какую нибудь библиотеку или макрос, как в VC++ 2010
Кто мешает компилять проект студийным компилятором в студии? QtCreator тоже умеет использовать студийный компилятор.

ЗЫЖ По умным указателям. Я их использую везде, где не критична скорость (а это 99% кода), потому что это удобно. Я взял за правило и забывать у меня не получается.
В случае с кутешным QObject лучше не использовать QSharedPtr и подобные, а использовать родительские отношения и QPointer.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: schmidt от Февраль 12, 2013, 21:28
Чтобы ничего нигде не текло - трубы нужно класть по проекту :) На собственных граблях знаю - лучше о таких вещах помнить сразу, а не искать инструменты для анализа утечек.

Чаще используйте локальные переменные на стеке, вместо new/delete. Если вы точно знаете, что объект вам нужен только в рамках работающей функции, в том числе с передачей его вглубь других функций, используйте локальные переменные функций и передавайте их по адресу. После выхода из текущей функции стек просто "очищается" и память освобождать явным образом нет необходимости.

Сокращайте размер участков кода, разбивайте код на короткие и логически ясные методы с хорошими именами - сможете избежать многих проблем заранее. В нескольких отдельных методах размером в 10-20 строк разобраться не в пример проще, чем в одном "монстре" на 100. Мыслите в терминах простых и ясных связей между компонентами программы (интерфейсов), а о конкретной реализации проще думать в рамках конкретного небольшого метода. Я думаю большинство проблем с утечками при таком подходе отпадут сами собой :)

Рекомендую на досуге почитать книгу Стива Макконнелла "Совершенный Код" - книга даёт хорошее понимание того, что считать хорошим кодом/стилем программирования и почему.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igors от Февраль 12, 2013, 21:40
Чтобы ничего нигде не текло - трубы нужно класть по проекту :)
...
Рекомендую на досуге почитать книгу Стива Макконнелла "Совершенный Код"
Ну развитие происходит по спирали. Когда князь Андрей лежал под большим и прекрасным небом - как мелок бы ему показался Стив Макконнелл ?

Это хорошо что Вы полны оптимизма и знаете "как правильно" - но это всего лишь начало следующего витка


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: schmidt от Февраль 13, 2013, 10:04
Цитировать
Это хорошо что Вы полны оптимизма и знаете "как правильно" - но это всего лишь начало следующего витка

Всецело с вами согласен, нет предела совершенству :) Разумеется, "идеальный подход" существует исключительно в теории, а грабли собрать бывает полезно самому. Ни в коем случае не посягаю на личное право каждого наступить на грабли  ;D Личный опыт бесценен, на одних книгах, конечно, далеко не уедешь.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: deMax от Август 23, 2013, 13:32
В нескольких отдельных методах размером в 10-20 строк разобраться не в пример проще, чем в одном "монстре" на 100. Мыслите в терминах простых и ясных связей между компонентами программы (интерфейсов), а о конкретной реализации проще думать в рамках конкретного небольшого метода. Я думаю большинство проблем с утечками при таком подходе отпадут сами собой :)
Не уверен что стоит заменять "монстра" из 100 строк, на 5 методов по 20 строк. Если отдельные части "монстра" могут быть полезны другим функциям - это отдельный разговор. Обилие функций в хиадерах способствует желанию выкинуть нафиг этот говнокод - плохая структура, намного плохой хреновой реализации.
Главное чтоб код был читабельным и чем меньше его будет при том же функционале, тем лучше(не в ущерб логике).


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Август 23, 2013, 13:35
Вы неправы, deMax.

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

Интерфейс - функция drawEllipse(QPoint ) - где рисовать.

А внутри идут функции расчёта, функции рисования, функции выбора/расчёта цвета и прочее.

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


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: voral от Август 23, 2013, 15:30
Наверное имелось ввиду, чтоб деление на отдельные методы не было просто ради деления по количеству строк. Если некие 20 строк используются только в одном месте кода нафига их выдирать в отдельный метод? Чтоб потом получить накладные расходы связанные с вызовом метода?

Много строк в методе это лишь сигнал проверить все ли так продумано. А визуально разделить можно пустыми строками и комментариями.

ИМХО


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Август 23, 2013, 15:37
Не. тут идёт дело о дальнейшей поддержке кода.

Пробежаться по 10 функциям и увидеть, что девятая выдаёт неверные данные - дело 5 секунд.

Пробежаться по функции в 100 строк, мониторя все переменные - бесценно, но бессмысленно.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: kambala от Август 23, 2013, 18:37
часто «монстров» не бьют на куски т.к. придется передавать тонну параметров, а сохранять их в полях класса не имеет смысла


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: voral от Август 23, 2013, 19:45
Не. тут идёт дело о дальнейшей поддержке кода.
Пробежаться по 10 функциям и увидеть, что девятая выдаёт неверные данные - дело 5 секунд.
Пробежаться по функции в 100 строк, мониторя все переменные - бесценно, но бессмысленно.

И тем не менее это имеет смысл, только в случае если для разбивки есть еще и логическое обоснование. Бить ради приведения количества строк к какомуто взятому с потолка числу строк - не понятен профт.. Для примера (сразу отбросим вариант когда выделен код который выделен по логике. Я о тех случаях когда строка/группа строк не имеет смысла если выкинуть остальные 90. Итак имеем:
1. вариант
Код:
метод1{
строка1
строка2
.....
строка10


строка11
строка12
......

строка 100
}
//2 вариант (строки взяты из первого варианта)
метод2_1
{
строка1
...
строка10
}
.....// несколько прочих методов которые по мере разработки появились

метод2_3
{
строка21
...
строка30
}

метод2_2
{
строка11
...
строка20
}

метод1 // метод который мы порезали
{
   Метод2_1
   Метод2_2
   Метод2_3
}

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

Нет правило такое есть и оно не плохое. Просто, имхо, не надо бросаться сразу дробить по количеству строк. А 100 раз подумать: почему код такой длинный? Можно ли его уменьшить в рамках одного метода? Можно ли выделить логически самостоятельные "куски"?.....    "не более Х строк в методе" - это не серьезно.....


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igors от Август 23, 2013, 19:58
Нет правило такое есть и оно не плохое. Просто, имхо, не надо бросаться сразу дробить по количеству строк. А 100 раз подумать: почему код такой длинный? Можно ли его уменьшить в рамках одного метода? Можно ли выделить логически самостоятельные "куски"?.....    "не более Х строк в методе" - это не серьезно.....
Не имеет значения длинный/короткий, "сколько писать" и.т.п. бьется по смыслу. Пример
Код
C++ (Qt)
for (TMap::const_iterator it = tmap.begin(); it != tmap.end(); ++it)
cout << *it << endl;
 
Должно быть выделено в метод или в утилиту, т.к. этот ф-ционал не завязан на текущий контекст.


Название: Re: как правильно работать с Qt, чтобы не было ут&#
Отправлено: vregess от Август 24, 2013, 07:32
На Вындоуз я пока на MSVC 2008, поэтому интересно что там за макрос такой в 2010 который Вы упоминаете?

я пользовался
_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
хочется хотя бы что то типа этого в Qt
что мешает и дальше пользоваться этим?

Я пользуюсь таким подходом: http://winfig.com/detecting-memory-leaks-in-qt-applications-with-visual-studio/ (http://winfig.com/detecting-memory-leaks-in-qt-applications-with-visual-studio/)
Меня пока устраивает.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: deMax от Февраль 14, 2014, 15:34
Не. тут идёт дело о дальнейшей поддержке кода.
Пробежаться по 10 функциям и увидеть, что девятая выдаёт неверные данные - дело 5 секунд.
Пробежаться по функции в 100 строк, мониторя все переменные - бесценно, но бессмысленно.
С точки зрения тестов согласен. Хотя хватает нюансов, девятая может не пройти так как на восьмую пришлось исключение которого нет в тесте(а это исключение формирует кривые данные или портит память, а тест проходит) - если что и не работает, то дебагером быстрее ошибку найдешь, чем замыленным глазом в "чистый код" смотреть.
Гадить в структуре ради тестов, не хочется. Правда писать длинные функции тоже не получается, ИМХО - как правило, чем меньше кода(при одинаковой его чистоте), тем легче он читается.
Цитировать
Как грится садясь в машину ты видишь интерфейс водятла. А под капотом проще разобраться, если оно по частям, а не одним комком.
Правильно, если там 5 частей и каждая состоит из 5 подчастей. А не 5 частей, в каждой 5 подчастей, в каждой подчасти еще по 5 подчасте, ... а потом смотришь и говоришь, а вот эти нижних 25 подчастей и 5 .cpp + .h файлов теперь надо удалить и заменить одной меленькой фунцией из библиотеки тойоты. (или выкинуть в помойку ущербный бензиновый двигатель, и поставить батарейку с компьютером и 4 моторчика).

И тем не менее это имеет смысл, только в случае если для разбивки есть еще и логическое обоснование.
Нет правило такое есть и оно не плохое. Просто, имхо, не надо бросаться сразу дробить по количеству строк. А 100 раз подумать: почему код такой длинный? Можно ли его уменьшить в рамках одного метода? Можно ли выделить логически самостоятельные "куски"?.....    "не более Х строк в методе" - это не серьезно.....
Согласен полностью.
Если код больше 30 строк надо на него глянуть, возможно мы не правы и стоит доработать структуру. А возможно в данном случае все нормально. Засорять обилием мусорных функций, которые вызываются в одном месте и не могут быть использованы где то еще, только структуру засорять(я глянул на такой код недописанный, но с кучей хиадеров и кучей классов и выкинул его, написал сам, почему то и функционала больше и все соответствует ТЗ и структура проще и понятнее - правда функций больше экрана в нем все равно нет).
10К строк хиадеров для проекта с функционалом Hello World хочется просто удалить и даже не вникать во всю эту "гениальность".

p.s. Хотя если над проектом работает много людей, то есть смысл раскидать на кучу функций, чтоб каждому по маленькому кусочку который он вылижет.
p.s.s. Все гениальное просто.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: vulko от Сентябрь 26, 2014, 14:30
Лучший способ избежать утечек, это заранее продумать архитектуру и правильно работать с памятью.
Т.е. ненужные объекты нужно удалять. Если есть new, должен быть delete. С QObject'ми проще, они могут удаляться сами при удалении родителя. Но эта схема не всегда применима в конкретной архитектуре приложения.

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

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

А самое важное не забывать эти простые правила, и будет вам счастье. В противном случае рискуете потратить кучу времени в будущем.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Tuxford от Август 21, 2015, 17:05
Не могу понять почему до сих пор в Qt не используются умные указатели. Немерено проблем можно было решить.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Old от Август 21, 2015, 18:40
Не могу понять почему до сих пор в Qt не используются умные указатели. Немерено проблем можно было решить.
Почему не используются - используются.
Есть QSharedPointer, QWeakPointer, QScopedPointer. А в Qt 5.4 наконец добавили QEnableSharedFromThis.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Август 21, 2015, 19:22
Мб потому, что умные указатели пусть чуть чуть, но замедляют работу.
Мб потому, что умные указатели не панацея, а лишь один из способов решения проблемы.
Мб потому, что разбирать ошибки с умными указателями в одних случаях проще, в других сложнее.
Мб потому, что это С++ :)
Мб потому, что код с умными указателями выглядит запутаннее.
Мб потому, что часть разработчиков их не любит :D


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igors от Август 22, 2015, 10:28
Мб потому, что ...
Ой  :) Скажите лучше прямо, напр "я неск раз сталкивался - и мне не очень понравилось".  По существу шаред - это попытка "сборщика мусора", т.е. если изначально все спланировано на шаред - то необходимость в delete отпадает.

Однако беда в том что "спланировать изначально" случается редко. Гораздо чаще уже имеется обильный код, без всяких шаред и обычно писаный др программистами. А тогда попытки шариться обычно печальны т.к. получается  "гремучая смесь" из таких и сяких указателей

 


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Tuxford от Август 25, 2015, 11:33
Мб потому, что умные указатели пусть чуть чуть, но замедляют работу.
Насколько? Использовал это дело в ембеддед. Никаких тормозов не было замечено. Возможно такое утверждение было верно 10 лет назад. Но сейчас?

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

Мб потому, что это С++ :)
А что есть Qt для С? :)

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

Мб потому, что часть разработчиков их не любит :D
Видать это большинство предпочитает ковырятся в поисках ликов.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Август 25, 2015, 14:25
C++ был создан с прямым управлением памятью. Умные указатели были созданы позднее для удобства.

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

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

PS программы без умных указателей имеют четкую архитектуру, ответственность за распределение памяти висит на программисте. С умными указателями ответственность частично снимается.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igors от Август 25, 2015, 15:16
Не любят именно за "своевольное" поведение. Но в этом весь смысл умных указателей, как уже говорили - это жалкая попытка ввести в C++ автоматический сборщик мусора.
О "жалкости" я ничего не говорил, это Вы уже от себя  :)

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

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

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

Был тут один (все рвался с туториалами), он быстро схавал идею "все шаред", но попытки применить на практике не имели успеха - только затянувшиеся разборки "почему же не работает". Насколько я помню Qt вернуло ему что-то "не шаред" - ото почалось...


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Tuxford от Август 27, 2015, 11:05
PS программы без умных указателей имеют четкую архитектуру, ответственность за распределение памяти висит на программисте. С умными указателями ответственность частично снимается.
По моему все больше зависит от задачи. В случае использования исключений использование умных указателей куда предпочтительнее. В таких случаях разобраться где-то что не удаляется, а также сильно усложняется контроль за динамически выделенными объектами.



Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Август 27, 2015, 13:12
Согласен, что зависит от задачи. Но таких задач очень мало :)


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Old от Август 27, 2015, 14:15
Согласен, что зависит от задачи. Но таких задач очень мало :)
Нет. Такие задачи практически все.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Ilia_Ivanov от Сентябрь 23, 2015, 19:03
1. Покажите пример того, как вы обычно создаёте новый класс, новый объект этого класса, как вызываете метод объекта этого класса и как удаляете объект этого класса.

Чуть раньше у меня было всё просто. Выясняем необходимость в объекте. Думаем минут пятнадцать, а правда ли объект нам необходим. Идем в Visual Studio, добавляем руками хедер, не забыв указать папку Include в папке проекта. Сразу добавляем в хедер гварды через Visual Assist, чтобы не было проблем, через контекстное меню. Дописываем после гвардов пустую строку, комментарий, зачем класс нужен, включаем TApplication.h - это основной хедер приложения. В нем уже включены все контейнеры Qt и много мелочей, дефайны разные, структуры, энумы. Пишем руками заголовок класса, если нужно унаследоваться, возвращаемся назад и дописываем хедер с классом, от которого наследование. Для всех агрегатированных членов-указателей пишем forward declarations, хедеры включаем в cpp-шник нашего класса. После открывающей { пишем или не пишем Q_OBJECT, если нет, то класс не Qt-шный, просто Visual C++. Сразу пишем каркас класса - ключевые слова protected, public, дефолтный конструктор, конструктор от QObject(или QWidget) и виртуальный деструктор. Пишем в секцию public пару методов, какие нужны в первую очередь. Делаем в Visual Assist Create Implementations, снимаем ненужные галочки, получаем реализацию всех методов. Дописываем реализацию и новые методы. Так всё было, но теперь по-другому! Пришла страшная информация, что без юнит-тестов проект обречён. Понял, почему прошлые проекты не доходили до конца, и перешел на TDD(тестирование через разработку). Теперь нужно сначала написать тесты, которые покрывают функциональность класса, по методу красный-зеленый-рефакторинг. Сначала пишем тест через QTest фреймворк, добиваемся, чтобы тест не прошёл, потом пишем класс по имеющимся требованиям, попутно очень тяжело и долго думаем, как так написать, чтобы конструкция вообще заработала. Потому что если без тестов всё как-нибудь поднимется и потом упадёт, то с тестами при ошибочной архитектуре даже не взлетит.
По отлову ошибок. 50 процентов рассчитываю отловить юнит-тестами, остальное дебагом. У меня однопоточка. Я установил кешер буфера обмена windows, прилепил его desk pin-ом на самый верх стопки окон. Очень удобно, но требует серьезного сосредоточения. Идём дебаггером, подозрительные места копируем, после закрытия программы имеем список багов и глюков, исправляем их.
По поводу утечек памяти. Нужно просто грамотно писать код. Запрещено: арифметика указателей полностью, сырые массивы типа int* = new int[5], расползание указателей. Разрешены: stl и qtl, массивы с контролем границ, умные указатели, создание как инициализация. Там еще много требований, всего не перечислишь. Смысл такой - нет этих опасных мест, нет утечек памяти. Без них можно и нужно обходиться. Как в C#.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igors от Сентябрь 24, 2015, 10:15
Так всё было, но теперь по-другому! Пришла страшная информация, что без юнит-тестов проект обречён. Понял, почему прошлые проекты не доходили до конца, и перешел на TDD(тестирование через разработку). Теперь нужно сначала написать тесты, которые покрывают функциональность класса, по методу красный-зеленый-рефакторинг. Сначала пишем тест через QTest фреймворк, добиваемся, чтобы тест не прошёл, потом пишем класс по имеющимся требованиям, попутно очень тяжело и долго думаем, как так написать, чтобы конструкция вообще заработала. Потому что если без тестов всё как-нибудь поднимется и потом упадёт, то с тестами при ошибочной архитектуре даже не взлетит
Долго, но, увы - безуспешно, я пытался выяснить в чем же прелести TDD здесь (http://www.prog.org.ru/index.php?topic=29149.msg213684#msg213684). Предложил показать преимущества этого подхода на простой студенческой задаче (парсинг obj файла). Ничего конкретного не увидел, только слова "ах как это хорошо". Жевать это все снова уже неинтересно

По поводу утечек памяти. Нужно просто грамотно писать код. Запрещено: арифметика указателей полностью, сырые массивы типа int* = new int[5], расползание указателей. Разрешены: stl и qtl, массивы с контролем границ, умные указатели, создание как инициализация. Там еще много требований, всего не перечислишь. Смысл такой - нет этих опасных мест, нет утечек памяти. Без них можно и нужно обходиться. Как в C#.
Глупость начальства повторять необязательно  :)



Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Сентябрь 24, 2015, 10:39
По поводу этих ограничений - работал одно время с коллегой, профи в С++. Ему поставили задачу - написать программу на C#. Да да, чтобы не было утечек, чтобы сборщик всё убирал и прочее.
У него ушло 2 дня на то, чтобы в C# был отключен сборщик, появилась арифметика указателей и С# оказался максимально приближен к С++ :)

При желании можно вообще пользоваться только безопасными методиками разработки. Вот только такие пути ведут в тупик трудноподдерживаемого кода :D


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Old от Сентябрь 24, 2015, 10:43
Глупость начальства повторять необязательно  :)
А в чем глупость начальства? В том, что они хотят обезопасить свой проект от кучи средних программистов, которые его делают?
Поэтому, проще заставить этих обезьян использовать нормальные средства не допускающие утечек в принципе, чем получить не работоспособный проект после нескольких лет разработки, потратив большую часть бюджета на з/п этих "специалистов".


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Сентябрь 24, 2015, 19:51
Old, затраты и сложность реализации из-за этих "обезопасностей" повышаются раз в 10-15, на мой взгляд.
Более того целый слой возможностей языка делается недоступным.
А получаем мы "отсутствие опасных мест", которые средним программистом обходятся на раз два.

Очень похоже на лечение сыпи методом ампутации. И проблема вроде решена, и сыпи на теле уже не осталось, однако сыпь (утечки) всё равно могут быть :D

PS не верю в прекращение использования таких мест. Тот же winapi полное нарушение всех правил. Т.е. мы и взаимодействовать не можем :D



Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Ilia_Ivanov от Сентябрь 24, 2015, 20:02
А получаем мы "отсутствие опасных мест", которые средним программистом обходятся на раз два.

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

Я почти не взаимодействую с winapi. Winapi - это ад, чем меньше его будет, тем лучше. Ему не помогут никакие средства, это не повод вводить небезопасную технику работы.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Old от Сентябрь 24, 2015, 20:07
Old, затраты и сложность реализации из-за этих "обезопасностей" повышаются раз в 10-15, на мой взгляд.
Какие затраты и сложности? Вы о чем? :)

Более того целый слой возможностей языка делается недоступным.
Что это за слой такой? :)

А получаем мы "отсутствие опасных мест", которые средним программистом обходятся на раз два.
Ну конечно. :)
Обойти "опасное место" в программе состоящей из главного окна и диалога не велика доблесть. :)

PS не верю в прекращение использования таких мест. Тот же winapi полное нарушение всех правил. Т.е. мы и взаимодействовать не можем :D
Это никак не связано с winapi. Взаимодействуйте по полной. :)


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Сентябрь 24, 2015, 22:05
Затраты на "а как сделать вот тут, чтобы не использовать обычные указатели, массивы и прочее".
Слой называется - прямое управление памятью, работа с указателями и массивами.
Обходятся при правильной архитектуре спокойно.
Как вы будете взаимодействовать с WinApi, если для него нужно выделять массивы, передавать тупые указатели и работать с памятью. Т.е. весь код работы с winapi оказывается за пределами этих правил.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Old от Сентябрь 24, 2015, 22:14
Затраты на "а как сделать вот тут, чтобы не использовать обычные указатели, массивы и прочее".
Нет здесь никаких затрат. Это все известно.

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

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

Как вы будете взаимодействовать с WinApi, если для него нужно выделять массивы, передавать тупые указатели и работать с памятью. Т.е. весь код работы с winapi оказывается за пределами этих правил.
Что за ерунда. Умные указатели никак с этим не пересекаются. А то что вы всегда выделяете массивы через new, говорит только о вашей квалификации. ;)
C winapi можно работать совсем без new.

И кстати, а какие функции winapi требуют обязательно выделять блоки на куче? Можно мне показать хотя бы 10 таких? :)


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Ilia_Ivanov от Сентябрь 24, 2015, 22:29
Ок, соглашаюсь и покидаю тему, не буду спорить. Всем доброго вечера.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Bepec от Сентябрь 25, 2015, 05:50
Присоединюсь, спор бессмысленен после слов
Цитировать
Именно поэтому лет 20 назад придумали умные указатели, которые все это решают.
.
Всё решают за нас, печаль.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igors от Сентябрь 25, 2015, 11:20
Я почти не взаимодействую с winapi. Winapi - это ад, чем меньше его будет, тем лучше. Ему не помогут никакие средства, это не повод вводить небезопасную технику работы.
Следуя этой логике следующим в "списке неиспользуемых" должен быть Qt - ведь хотя бы те же виджеты (о ужас!) просто указатели. что совершенно НЕБЕЗОПАСНО!!!  :)



Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Old от Сентябрь 25, 2015, 11:45
Следуя этой логике следующим в "списке неиспользуемых" должен быть Qt - ведь хотя бы те же виджеты (о ужас!) просто указатели. что совершенно НЕБЕЗОПАСНО!!!  :)
Ну это как написать. :)
Цитата из вашего букваря:
Код
C++ (Qt)
   const QWidget *const p = new QWidget();
   // is equivalent to:
   const QScopedPointer<const QWidget> p(new QWidget());
 
   QWidget *const p = new QWidget();
   // is equivalent to:
   const QScopedPointer<QWidget> p(new QWidget());
 
   const QWidget *p = new QWidget();
   // is equivalent to:
   QScopedPointer<const QWidget> p(new QWidget());
 


Название: Re: как правильно работать с Qt, чтобы не было ут&#
Отправлено: andron81_81 от Декабрь 05, 2023, 09:34
Следуя этой логике следующим в "списке неиспользуемых" должен быть Qt - ведь хотя бы те же виджеты (о ужас!) просто указатели. что совершенно НЕБЕЗОПАСНО!!!  :)
Ну это как написать. :)
Цитата из вашего букваря:
Код
C++ (Qt)
   const QWidget *const p = new QWidget();
   // is equivalent to:
   const QScopedPointer<const QWidget> p(new QWidget());
 
   QWidget *const p = new QWidget();
   // is equivalent to:
   const QScopedPointer<QWidget> p(new QWidget());
 
   const QWidget *p = new QWidget();
   // is equivalent to:
   QScopedPointer<const QWidget> p(new QWidget());
 

понимаю, вы писали в 2015. А сейчас использование классических указателей с new , delete в 2023 не является ещё плохим тоном ?
а то я сам напрограммировал классикой , а может надо умные использовать или же в QT не считается преступной халатностью использовать классику ?  ???


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: ssoft от Декабрь 06, 2023, 10:34
Да уж наворотили в Qt всего ;).

Архитектура Qt закладывалась во времена без unique_ptr, shared_ptr и move семантики.
Но вопросы владения ресурсами и механизм RAII никто не отменял.

Как разработчик будет управлять  ресурсами - это его дело.
Можно new/delete использовать и сырые указатели (типа классические), но это трудоемко в плане подчистки ресурсов. Как минимум нужно в деструкторе удалить, а желательно ещё учесть возможность обработки исключений. Умные указатели unique_ptr, shared_ptr и другие решают задачу подчистки ресурсов, с ними проще.

Разработчики Qt в своей архитектуре смешали вопрос иерархии экземпляров объектов и вопрос владения, заложив правило, что верхний в иерархии объект удаляет объекты ниже в иерархии. Это привело к тому, что в Qt традиционно используют сырые указатели. Тем не менее, сами разработчики Qt рекомендуют использовать unique_ptr для управления ресурсами (стандартный почти аналог QScopedPointer).

При использовании сырых указателей классической ошибкой новичков является не указание родителя у экземпляра объекта (чаще всего this)

Код
C++ (Qt)
QObject * obj = new QObject; // должно быть QObject( this )
 

В этом случае никто не владеет объектом, куда указывает obj => потенциальные утечки ресурсов памяти.

В случае с умным указателем

Код
C++ (Qt)
unique_ptr< QObject > obj = make_unique< QObject >();
 

ресурсом владеет умный указатель, который в любом случае удалит объект, на который указывает obj.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Igor_S от Декабрь 09, 2023, 13:30
Разработчики Qt в своей архитектуре смешали вопрос иерархии экземпляров объектов и вопрос владения, заложив правило, что верхний в иерархии объект удаляет объекты ниже в иерархии. Это привело к тому, что в Qt традиционно используют сырые указатели.
Не вижу ничего плохого а этом правиле. Ну хорошо, а как же должна выглядеть связка парент-чайлд в свете новых достижений семантики?  Парент владеет чайлдами? Да, стало быть все равно парент должен иметь контейнер чайлдов. Или (теперь уже) вумных указателей. Да, но "юники" копировать нельзя, а контейнер потребует. Слышал как-то это обходится "муванием". И как тогда удалять тот же виджет (чайлд)?

Да уж наворотили в Qt всего ;).
Ах как мы добродушны и снисходительны  :)


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: ssoft от Декабрь 11, 2023, 16:24
Проблема владения не редкий вопрос на форуме), например, Про деревянный айтем (http://www.prog.org.ru/topic_32302_0.html) )). Паттерн parent-child, как раз про отношение часть-целое, отношение владения.

В архитектуре QObject владение child, вроде как, передается parent, а вроде как и нет. Никто не мешает удалить child напрямую, минуя parent. Такое вот двойное управление ресурсами.

Как следствие вопросы типа должен ли я озаботится о зачистке памяти? (http://www.prog.org.ru/index.php?topic=33497), так как интуитивно не понятно, в каком случае Qt почистит ресурсы, а в каком нет. Постоянно нужно в доки глядеть).
Но я уверен, что >90% разработчиков этот вопрос никак не волнует и интерпретируется даже, как удобство).

Цитировать
Слышал как-то это обходится "муванием". И как тогда удалять тот же виджет (чайлд)?

Можно и с move и без него. Удалять виджет следовало бы либо с помощью API владельца (parent), либо сначала извлечь child из parent, а затем удалять.
Здесь расписан пример реализации иерархии tree-example (http://www.prog.org.ru/index.php?topic=32302.msg238745#msg238745). Отношение parent-child реализована для класса Node.


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: Old от Декабрь 11, 2023, 17:39
например, Про деревянный айтем (http://www.prog.org.ru/topic_32302_0.html) )).
Эх, какие были срачи... Ушла эпоха. :)

Но хорошо что Igors нашелся (а то я даже беспокоиться начал - не сарказм), значит еще пообсуждаем. :)


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: kambala от Декабрь 11, 2023, 23:33
Но хорошо что Igors нашелся (а то я даже беспокоиться начал - не сарказм), значит еще пообсуждаем. :)
ABBAPOH тоже очень беспокоился, что больше нет животрепещущих тем :)


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: tux от Декабрь 12, 2023, 21:38
Чтоб был срач - нужно, чтобы был заинтересованный народ. Современный народ, по бОльшей части, в винде чалится. А что можно обсуждать на подоконнике?  ;D


Название: Re: как правильно работать с Qt, чтобы не было утечек памяти?
Отправлено: andron81_81 от Декабрь 14, 2023, 12:47
срач был в sql.ru вот там срач так срач был.