Russian Qt Forum
Ноябрь 22, 2024, 03:53 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2 3 4   Вниз
  Печать  
Автор Тема: как правильно работать с Qt, чтобы не было утечек памяти?  (Прочитано 59916 раз)
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? Может, какие то утилиты?



Заранее очень очень благодарю!
« Последнее редактирование: Октябрь 01, 2012, 15:36 от Setner » Записан
mutineer
Гость
« Ответ #1 : Октябрь 01, 2012, 15:35 »

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

А чтобы объект удалился автоматически мало просто отнаследовать его от QObject, надо еще ему родителя задать
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #2 : Октябрь 01, 2012, 16:11 »

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

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

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

Книги, Шлее и др. может и неплохи, но практического опыта не заменят
Записан
Setner
Гость
« Ответ #3 : Октябрь 01, 2012, 16:52 »

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

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

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

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

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


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

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


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

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


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

« Последнее редактирование: Октябрь 01, 2012, 17:06 от Setner » Записан
mutineer
Гость
« Ответ #4 : Октябрь 01, 2012, 16:55 »

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

Так же, как и просто в С++ - например засовыванием вывода в консоль в деструктор объекта
Записан
Setner
Гость
« Ответ #5 : Октябрь 01, 2012, 16:58 »

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

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

Хм, то есть пишем свои костыли. Понятно. Благодарю!
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #6 : Октябрь 01, 2012, 18:34 »

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

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

Если человек знает и любит C/C++, то изучение Qt будет легким и приятным. И наоборот  Улыбающийся
Записан
navrocky
Гипер активный житель
*****
Offline Offline

Сообщений: 817


Погроммист


Просмотр профиля
« Ответ #7 : Октябрь 01, 2012, 19:08 »

Ну под винду же полно инструментов для отлова ошибок при работе с памятью:

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

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

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

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

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

Гугль в помощь
schmidt
Гость
« Ответ #8 : Февраль 12, 2013, 21:28 »

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

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

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

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

Сообщений: 11445


Просмотр профиля
« Ответ #9 : Февраль 12, 2013, 21:40 »

Чтобы ничего нигде не текло - трубы нужно класть по проекту Улыбающийся
...
Рекомендую на досуге почитать книгу Стива Макконнелла "Совершенный Код"
Ну развитие происходит по спирали. Когда князь Андрей лежал под большим и прекрасным небом - как мелок бы ему показался Стив Макконнелл ?

Это хорошо что Вы полны оптимизма и знаете "как правильно" - но это всего лишь начало следующего витка
Записан
schmidt
Гость
« Ответ #10 : Февраль 13, 2013, 10:04 »

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

Всецело с вами согласен, нет предела совершенству Улыбающийся Разумеется, "идеальный подход" существует исключительно в теории, а грабли собрать бывает полезно самому. Ни в коем случае не посягаю на личное право каждого наступить на грабли  Смеющийся Личный опыт бесценен, на одних книгах, конечно, далеко не уедешь.
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #11 : Август 23, 2013, 13:32 »

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

Вы неправы, deMax.

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

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

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

Как грится садясь в машину ты видишь интерфейс водятла. А под капотом проще разобраться, если оно по частям, а не одним комком.
Записан
voral
Гость
« Ответ #13 : Август 23, 2013, 15:30 »

Наверное имелось ввиду, чтоб деление на отдельные методы не было просто ради деления по количеству строк. Если некие 20 строк используются только в одном месте кода нафига их выдирать в отдельный метод? Чтоб потом получить накладные расходы связанные с вызовом метода?

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

ИМХО
Записан
Bepec
Гость
« Ответ #14 : Август 23, 2013, 15:37 »

Не. тут идёт дело о дальнейшей поддержке кода.

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

Пробежаться по функции в 100 строк, мониторя все переменные - бесценно, но бессмысленно.
Записан
Страниц: [1] 2 3 4   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.054 секунд. Запросов: 23.