LINUX.ORG.RU

Почему два раза вызывается деструктор?

 , ,


0

4

Делаю программу, в которой нужно запускать терминальные команды в самодельном эмуляторе консоли. Происходит это с помощью «вспомогательного» класса CommandRun и класса-диалога ConsoleEmulator .

В классе основного окна MainWindow создан приватный член класса CommandRun:

CommandRun *syncroCommandRun;

В конструкторе MainWindow он инициализируется и запоминается в глобальный объект globalParameters.
syncroCommandRun=new CommandRun( this );
globalParameters.setSyncroCommandRun( syncroCommandRun );
(Этот globalParameters по сути ничего не делает, просто помнит указатель, проблема не в нем).

Класс CommandRun унаследован от QObject. При создании объекта syncroCommandRun конструктору передается указатель на родительский объект this, поэтому в деструкторе MainWindow никаких команд delete нет, потому что этот объект должен сам корректно удалиться как дочерний для MainWindow. Это обычное дело для Qt.

Если запустить демонстрационный пример, и сразу нажать кнопку закрытия окна [x], то закрытие программы произойдет нормально, без ошибок.

Если же запустить демонстрационный пример, нажать в нем кнопку Run (мигнет окно запуска процесса), и нажать кнопку закрытия окна [x], то в консоль будет выдано:
Программа неожиданно завершилась.

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

https://anonfiles.com/18F8h8u7oe/_2020-04-28_16-11-44_png

Я не пойму, почему так происходит.

Демонстрационный пример тут: https://anonfiles.com/R541h7udoc/qtSample_zip

Те же файлы на dropmefiles: https://dropmefiles.com/s92FS

★★★★★

Последнее исправление: Xintrea (всего исправлений: 1)

В деструкторе значения проверяются на nullptr, а в CommandRun::removeProcessAndConsole после удаление объектов указатели не сбрасываются в nullptr. Вот и ошибки.

И на самом деле код не входит в деструктор дважды, то просто компилятор генерирует ещё один «деструктор», который смещает this при виртуальном вызове деструктора и потом вызывает реальный деструктор.

xaizek ★★★★★
()

У меня ни картинка ни пример не грузятся:

При соединении с anonfiles.com произошла ошибка. PR_CONNECT_RESET_ERROR

Beewek ★★★
()

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

deep-purple ★★★★★
()
Ответ на: комментарий от Xintrea

Когда пользователь нажимает крестик, вызывается onManualCloseProcess, который вызывает removeProcessAndConsole, в котором производится удаление m_process. А затем m_process повторно удаляется в деструкторе CommandRun. Чтобы такого не случалось, надо после удаления m_process обнулить его.

Beewek ★★★
()

Есть информация, что на cdn-35.anonfiles.com размещены нежелательные программы. Вы можете проигнорировать риск и перейти на этот небезопасный сайт.

Узнайте больше о нежелательных программах на сайте Правила в отношении нежелательного ПО. Узнайте больше о Защите от фишинга и вредоносных программ в Firefox на сайте support.mozilla.org.

bhfq ★★★★★
()

Под винду не собирается. Не хватает include «Windows.h» для GetACP() GetOEMCP()

if(m_process->state()==QProcess::Running and m_process->processId()<=1) {

and

Что это и зачем?

Падает потому что m_process указатель в деструкторе указывает на удаленный объект. Удаление m_process выполняется в removeProcessAndConsole.

Рекомендую хранить указатели внутри QPointer.

if(m_process) не будет работать если руками не устанавливать указатель в NULL после delete (или использовать умные указатели вроде QPointer)

anonymous
()
Ответ на: комментарий от anonymous

and

Что это и зачем?

Логическое и. Что ещё это может быть?

anonymous
()
Ответ на: комментарий от anonymous

MSVC и стандарт это несовместимые вещи.

anonymous
()
Ответ на: комментарий от anonymous

это говно не следует стандарту

anonymous
()
Ответ на: комментарий от anonymous

В свежей студии с /permissive- переправлять не нужно.

anonymous
()
Ответ на: комментарий от xaizek

И на самом деле код не входит в деструктор дважды, то просто компилятор генерирует ещё один «деструктор», который смещает this при виртуальном вызове деструктора и потом вызывает реальный деструктор.

Долго тебя понимал... Я бы выразился так:

На самом деле код не входит в деструктор дважды, это просто компилятор генерирует «псевдо-деструктор», который изменяет this при виртуальном вызове деструктора. И этот «псевдо-деструктор» вызывает нужный реальный деструктор.

Xintrea ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.