QToolButton crashes on clicked and window destruction - c++

I have asked the question QWidget::repaint: Recursive repaint detected on Windows in Debug without creation of new threads. It turned out that the crash (on Windows in DEBUG mode) is due the fact that auto-generated ui file contained:
<widget class="QToolButton" name="button_logout">
</widget>
which would generate the code
QToolButton *button_logout;
button_logout = new QToolButton(widget_session_list);
button_logout->setObjectName(QString::fromUtf8("button_logout"));
header_layout->addWidget(button_logout);
So having a clicked event due to this connection:
...
connect(_ui->button_logout, &QToolButton::clicked, this, &ViewImpl::performLogout);
...
void ViewImpl::performLogout()
{
emit onLogout();
}
led to the crash with QWidget::repaint: Recursive repaint detected after the window would be hidden and deleted as a reaction on the signal onLogout().
However, I discovered that if I replace the QToolButton with QPushButton I do not get the crash and everything is fixed.
So my question is why? What is wrong with the QToolButton? And why is the problem on Windows in Debug mode and I do not have it on Linux or on Window in Release mode. Honestly, I have already encountered strange crashes on Windows in Debug mode for Qt. E.g., I remember once that QVariantList failed there, so I got rid of it. I must note here that I build against debug qt libraries and tried \MT, \MDd, and \MTd runtime libraries.

Probably your shutdown / logout logic is flawed: I guess, that you delete the object from which you are running your logout code. Try to replace the call to delete() with
deleteLater() and see what happens. For further diagnosis, we'd need more information about your object tree, construction and destruction.
It has absolutely nothing to do with the kind of button you are using, that is absolutely accidental.

Related

No such signal QObject::aboutToClose()

Constant jumps from release to debug made me pay attention to the fact that when closing the release version of the application (opened directly in Qt Creator, before WinDeployeeQt), this is displayed in the console:
qt.core.qobject.connect: QObject::connect: No such signal QObject::aboutToClose()
although I do not use this signal and did not redefine it. I have only redefined this:
void MainWindow::closeEvent(QCloseEvent *event) {
ClearNotes();
ClearClientOutputContacts();
ClearClientRedactContacts();
ClearContactOutputCompanies();
ClearDocuments();
ClearNewClientContacts();
event->accept();
}
in which I clear all dynamic fields, if any. The question is, close your eyes to this or try to understand where this message comes from? (This is not present in debug mode, only observed in release mode).

Qt app non-deterministically crashes on calling QMessageBox::question()

I am seeing a strange crash in a Qt app that I am working on, and I am wondering if anyone has seen something similar or knows what the reason could be.
The crash is due to an access violation and occurs in around 30% of the cases when a call to QMessageBox::question() is made. The app only crashes in Release mode (never in Debug).
The code that causes the crash looks completely innocuous:
QMessageBox::question(
this,
QString("Deleting configuration"),
QString("Are you sure you want to delete this configuration?"));
It does not matter if the dialog is created with a static function call (like above) or explicitly. Other standard dialogs that have an icon (QMessageBox::critical(), QMessageBox::information(), etc.) also cause this crash, but interestingly a default QMessageBox dialog without any icons never crashes. However, the crash appears again after adding a standard icon through setIcon():
QMessageBox dialog;
dialog.setText("Blah blah blah");
dialog.setIcon(QMessageBox::Question);
dialog.exec();
Could it have something to do with the standard icons in these dialogs? The crash only occurs on the first dialog display; once a single dialog has displayed without a crash, all subsequent ones will work fine.
The Qt version is 5.12.2 and the app is compiled with the Visual Studio 2017 x64 C++ compiler.

Qt application crash upon startup at MainWindow.Show() call

I'm trying to find out the reason of the crash of my Qt application, the debug doesn't contain much information available hence the difficult to find the reason... after using breakpoints, the closest I found was the line the crash might be at w.show() call (the application's GUI frooze before any button or anything at all show up). My main function is exactly this:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
// disable Window's maxminize button
const Qt::WindowFlags flags = w.windowFlags() ^ Qt::WindowMaximizeButtonHint;
w.setWindowFlags(flags);
w.show();
return a.exec();
}
when the line where w.show() is reached, the application starts (but not properly, the GUI frooze, as I mentioned before) and after several minutes I got a SEGFAULT and the debugger look like this:
How can I fix this? I'm on this has been days, trying to get the debugger give more information so that I can trace back the SEGFAULT reason but without the debugger information like this, I have no idea what to do.
My Qt version:
There are various ways to tackle such a problem, assuming you can't provide an MCVE:
Strip the elements of MainWindow one by one, first from the constructor, and see what creates the crash
If stripping elements from the constructor helps, then restore parts of it, and run the debugger to study what causes the freeze
Keep in mind that freezing in GUI programs usually means the event loop is blocked. If you're calling QApplication::processEvents() anywhere, consider removing that.
Finally, if everything fails, you're gonna have to go to a linux system, and recompile Qt in debug mode (debug + release never worked for me), and track the event loop and see, in code, what freezes your GUI.
The reason I'm recommending Linux is because gdb is great, and cdb is horrible at this. If you have VS enterprise, you could try its debugger too.
Good luck.
The part of original code that has a problem (fixed) :
// disable Window's maximize button (use bitwise [and-not]&~ and not [xor]^)
const Qt::WindowFlags flags = w.windowFlags() &~ Qt::WindowMaximizeButtonHint;
w.setWindowFlags(flags);
or that same effect can be achieved by:
w.setWindowFlag(Qt::WindowMaximizeButtonHint, false);
Found solution!
Hope it's useful to anyone with same issue:
In the debug messages I found out the crash was result from GBIEH.dll dll. Googling it I found it's related to internet banking (I guess when my application tried to use that dll the IB's application take this as a kind of attack hence the crash, my guess). I just removed the internet banking programa and the application worked fine.

A way to forcefully close modal QFileDialog on Mac

I have a Qt application which at some point calls QFileDialog::getOpenFileName. However, at any point my application can get an event which will make this file dialog irrelevant, so I want to forcefully close it.
This is my way of trying to close this dialog:
QWidget *modalWidget = QApplication::activeModalWidget();
if (modalWidget)
modalWidget->close();
This works on Windows, but I get strange behavior on Mac. Instead of closing, it hides the dialog instead. Execution never leaves QFileDialog::getOpenFileName call and since it's a modal dialog, underlying app becomes permanently frozen.
For the sake of closure, I ended up closing the dialog by calling native [NSApp abortModal].
Note that this workaround might not be needed if this issue was fixed in the recent Qt releases (haven't checked since Qt 5.8).

Invalidate() debug assertion failed message (MFC, VC++)

I've made a custom control, and when I want it to repaint on the screen I call Invalidate(), and afterwards UpdateWindow(), but i get message:
debug assertion failed for a file afxwin2.inl in line 150 which is:
AFXWIN_INLINE void CWnd::Invalidate(BOOL bErase)
{ ASSERT(::IsWindow(m_hWnd)); ::InvalidateRect(m_hWnd, NULL, bErase); }
The thing is that when I run the same app in release mode, it doesn't report any message! So this clue makes me think it's about some environment configuration I should change.
What do you think?
Thanks.
Well,
ASSERT(::IsWindow(m_hWnd));
is an assertion. Assertions are statements which verify that something is true and kill your program if it's not. They're intended to be used for debugging and development rather than for being in the program once it has been released, so they are normally only compiled in in debug builds. So, it wouldn't be there in a release build, and you wouldn't get the error message. That does not mean that there isn't a problem in the release build. It just means that that it's not running the statement to check whether there's a problem.
I don't know a lot about the error in question, but looking at it,
::IsWindow(m_hWnd)
is obviously false (hence the error message). The documentation for IsWindow() would appear to indicate that the problem is that the window handle in question is not a handle for a valid window. Perhaps it hasn't been created properly, or it has already been destroyed. You'll have to figure out why your window handle is invalid.
A quick google search for "mfc iswindow" brings up this thread on msdn which might be of help to you.
You call Invalidate before window is created or after window is destroyed. Quick fix is to test for ::IsWindow(m_hWnd) before Invalidate call. To really fix this bug, find why Invalidate is called when window doesn't exist. For example, attempt to invalidate window from its constructor causes this assertion.
You have called Invalidate() on an CWnd-derived class, but that window's m_hWnd member has not been built yet. You should call the Create (or CreateEx) method first, in order to build it (or use a method that does all that for you, like DoModal() ).