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

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

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Правильное освобождение ссылочных полей объекта  (Прочитано 8711 раз)
UltraPenguin
Гость
« : Май 28, 2014, 11:07 »

Доброго времени суток!

После прогона проги через valgrind последний выдал множество ошибок такого рода:
Цитировать
Address 0x10835098 is 8 bytes inside a block of size 16 free'd
==26294==    at 0x4C279DC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==26294==    by 0x43674A: CReadWriteINIParam::~CReadWriteINIParam() (ReadWriteINIParam.cpp:59)

Конкретно ругается на строку:
Код:
delete settings;

Само поле settings объявлено так:
Код:
QSettings *settings;

И его инициализация происходит в конструкторе класса CReadWriteINIParam через оператор new.
Почему возникает ошибка обращения к освобожденной памяти, если единственное освобождение находится как раз в деструкторе класса? Непонимающий

Если закомментить строку с delete, ошибки пропадут, но возрастут утечки памяти судя по тому, что выдает все тот же valgrind.

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

Заранее спасибо!
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #1 : Май 28, 2014, 11:43 »

При создании settings parent задавался?
Записан

Qt 5.11/4.8.7 (X11/Win)
UltraPenguin
Гость
« Ответ #2 : Май 28, 2014, 11:49 »

Нет не задавался. Честно говоря, забыл про него, теперь понятно как побороть утечку. Спасибо большое!
Получается если не задан родитель, то поле считается освобожденным к моменту вызова деструктора?
Записан
GreatSnake
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2921



Просмотр профиля
« Ответ #3 : Май 28, 2014, 11:55 »

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

Qt 5.11/4.8.7 (X11/Win)
UltraPenguin
Гость
« Ответ #4 : Май 28, 2014, 13:54 »

ну откуда то ошибка об обращении к свободной памяти берется?
Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #5 : Май 28, 2014, 23:16 »

ну откуда то ошибка об обращении к свободной памяти берется?

Телепаты в отпуске. Вы даже минимальный код иллюстрирующий проблему не привели.

1. В вашей ИДЕ сделайте "показать использование" на подозрительную переменную. И рассмотрите все места где создается, где меняется, где прибивается.

2. Если первое не помогло - используйте пошаговую отладку. Вам нужно воссоздать картину действия.
Записан
UltraPenguin
Гость
« Ответ #6 : Май 29, 2014, 15:10 »

Цитировать
Телепаты в отпуске. Вы даже минимальный код иллюстрирующий проблему не привели.
Вроде как телепаты и не требовались. В первом посте, как мне кажется, все достаточно детально описано. Но если нужен минимальный иллюстрирующий код то пожалуйста:
Код:
class CReadWriteINIParam
{
    private:
        QSettings* settings;
}

CReadWriteINIParam::CReadWriteINIParam()
{
    settings = new QSettings(sFileININame, QSettings::IniFormat);
}

CReadWriteINIParam::~CReadWriteINIParam()
{
    if (settings != NULL)
        delete settings;
}

Не вижу как это может помочь прояснить ситуацию правда.
И как пошаговая отладка поможет в деле распознавания адресации к освобожденной памяти, если явного освобождения в коде нет (до вызова деструктора)Непонимающий
Записан
UltraPenguin
Гость
« Ответ #7 : Май 29, 2014, 15:20 »

1. В вашей ИДЕ сделайте "показать использование" на подозрительную переменную. И рассмотрите все места где создается, где меняется, где прибивается.

2. Если первое не помогло - используйте пошаговую отладку. Вам нужно воссоздать картину действия.

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

 Смеющийся

Простите, не сдержался Показает язык
Записан
UltraPenguin
Гость
« Ответ #8 : Май 29, 2014, 15:43 »

При создании settings parent задавался?

Я что-то рано обрадовался по поводу возможности указать родителя. Родителем ведь может быть только класс QObject и его наследники! Неужели единственный способ не вызывать гнев valgrinda, это наследовать ненужный функционал QObject?

Хотя, конечно, можно просто закрыть глаза на данные строки valgrinda, память то чистится в любом случае...
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #9 : Май 29, 2014, 18:21 »

зачем сеттингсам задавать родителя и создавать их в куче?
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
sergek
Гипер активный житель
*****
Offline Offline

Сообщений: 872


Мы должны приносить пользу людям.


Просмотр профиля
« Ответ #10 : Май 29, 2014, 19:13 »

Интересная у вас тут беседа завязалась Улыбающийся
Хотя, конечно, можно просто закрыть глаза на данные строки valgrinda, память то чистится в любом случае...
Не то слово - даже дважды:
Цитировать
Memcheck keeps track of the blocks allocated by your program with malloc/new, so it can know exactly whether or not the argument to free/delete is legitimate or not. Here, this test program has freed the same block twice. As with the illegal read/write errors, Memcheck attempts to make sense of the address freed. If, as here, the address is one which has previously been freed, you wil be told that -- making duplicate frees of the same block easy to spot. You will also get this message if you try to free a pointer that doesn't point to the start of a heap block.
А попробуйте закомментировать весь код, использующий созданный settings, кроме new/delete и прогнать через valgrind. Интересно, останется ошибка?
Записан

Qt 5.13.0 Qt Creator 5.0.1
Win10, Ubuntu 20.04
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #11 : Май 29, 2014, 23:13 »

Цитировать
Телепаты в отпуске. Вы даже минимальный код иллюстрирующий проблему не привели.
Вроде как телепаты и не требовались. В первом посте, как мне кажется, все достаточно детально описано. Но если нужен минимальный иллюстрирующий код то пожалуйста:
Код:
class CReadWriteINIParam
{
    private:
        QSettings* settings;
}

CReadWriteINIParam::CReadWriteINIParam()
{
    settings = new QSettings(sFileININame, QSettings::IniFormat);
}

CReadWriteINIParam::~CReadWriteINIParam()
{
    if (settings != NULL)
        delete settings;
}

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

Эта выдержка кода не иллюстрирует проблему. И вообще не соответствует действительности.
Непонятно для чего вы её привели вместо того, что бы привести выдержку реального кода.
Возможно вам просто лень решать собственную проблему.

По поводу пошаговой отладки: программист полагает. А программа располагает.
Очевидно, что в программе происходят действия, которых вы не ожидаете.

Пошаговая отладка может помочь понять, в чем именно вы ошиблись.


« Последнее редактирование: Май 29, 2014, 23:27 от _Bers » Записан
_Bers
Бывалый
*****
Offline Offline

Сообщений: 486


Просмотр профиля
« Ответ #12 : Май 29, 2014, 23:18 »

Код:
CReadWriteINIParam::~CReadWriteINIParam()
{
    if (settings != NULL)
        delete settings;
}

Этот код вызывает сомнение.

1. Вы допускаете, что к моменту запуска диструктора setting может быть равен nullptr ?
Каким образом это может произойти?
 --- конструктор не захватил ресурс по указателю?
 --- существуют методы, которые могут освободить ресурс в процессе жизни экземпляра класс?

 Если второй пункт имеет место быть - стоит рассмотреть его внимательнее.

2. Нет ни одной причины проверять указатель на nullptr перед освобождением ресурса.
Записан
UltraPenguin
Гость
« Ответ #13 : Июнь 03, 2014, 16:45 »

Эта выдержка кода не иллюстрирует проблему. И вообще не соответствует действительности.
Подождите, вы просили МИНИМАЛЬНЫЙ код иллюстрирующий проблему. Вот он.

Непонятно для чего вы её привели вместо того, что бы привести выдержку реального кода.
По разным соображениям, но в первую очередь из-за того, что его МНОГО.

По поводу пошаговой отладки: программист полагает. А программа располагает.
Очевидно, что в программе происходят действия, которых вы не ожидаете.
Пошаговая отладка может помочь понять, в чем именно вы ошиблись.
Ок, я вас понимаю. Но я спрашивал о том, КАК конкретно проверить указывает ли указатель (масло так маслит Смеющийся)  на свободную память или нет с помощью дебагера если в коде по ходу выполнения НЕТ delet'ов кроме указанного мной в минимальном примере кода?

UPD: я вот не в курсе как это сделать. Возможно, недоучил. Но скорее всего это просто никак не узнать)
Записан
UltraPenguin
Гость
« Ответ #14 : Июнь 03, 2014, 16:49 »

Цитировать
А попробуйте закомментировать весь код, использующий созданный settings, кроме new/delete и прогнать через valgrind. Интересно, останется ошибка?
ок попробую, напишу результат
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


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