Solved Segfault when calling QWidget::show (on Debian 9)
-
@Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):
char **argv and char *argv[] is actually the same
I know and I agree! That's why I said it "That's a very odd one!", and I didn't see why that declaration mattered. More to the point I wanted to read what the original "solution" post had said about this, but it's gone into the blue yonder.....
Let's wait and see whether the OP here finds this really has something to do with the problem now....
-
@JonB said in Segfault when calling QWidget::show (on Debian 9):
Meanwhile I see now you go
MyApplication::mfParseArguments(int, char**) ()
, etc. It ends up calling yourMyApplication::mfRun(int, char**, QString&) ()
. What does that do withargv
?Well, actually, in
MyApplication::mfParseArguments(int argc, char** argv)
theargv
frommain
is taken and a copy of it is created. This copy has one extra-e
argument and is thus one element longer. Something in essence like this (original code slightly modified):char** newArgvs; newArgvs = new char*[argc+1]; for(i = 0; i < argc + 1; i++) { newArgvs[i] = new char[256]; } strcpy(newArgvs[0], argv[0]); strcpy(newArgvs[1], "-e"); for(i = 1; i < argc; i++) { strcpy(newArgvs[i+1], argv[i]); } argc++;
and then at the end of
MyApplication::mfParseArguments
thatnewArgvs
is passed toICService::mfParseArguments
:return ICService::mfParseArguments(argc, newArgvs, false);
which in its turn then passes this info through to
ICService::mfExec
and that one then passes it toMyApplication::mfRun
which callsQWidget::show
that segfaults. -
The question is - where do you pass it to your Q(Core)Application.
-
@Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):
The question is - where do you pass it to your Q(Core)Application.
That is indeed a good question... it is currently not yet clear to me where the single instance of the
QApplication
class is created. I'll have to spend some more time with the code to figure that out, and report back once I know more.In the meanwhile: is it crucial that
argc
andargv
are passed to that singleQApplication
instance, and could that be the reason for a segfault when callingQWidget::show()
? -
@Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):
@Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):
The question is - where do you pass it to your Q(Core)Application.
That is indeed a good question... it is currently not yet clear to me where the single instance of the
QApplication
class is created. I'll have to spend some more time with the code to figure that out, and report back once I know more.OK. For as far as I can see it now, the call to
QApplication(argc, argv)
happens inICService::mfExec
before the call toMyApplication::mfRun
and is with the newargc
andargv
, where the newargc
is one more than the oldargc
(passed tomain
), and the newargv
has one element (-e
) more than the oldargv
(that was passed tomain
).Is it troublesome if in a call to
QApplication(newArgc, newArgv)
we have thatnewArgc != argc
andnewArgv
is not the same asargv
, whereargc
andargv
were the arguments passed tomain
? -
@Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):
for(i = 1; i < argc; i++)
{
strcpy(newArgvs[i+1], argv[i]);
}I shall be surprised if it is this, but....
I think your code is not 100% technically correct. You do not
NULL
terminate your new vector. Technically you should find your originalargv
had an extra element at the end:argv[argc] == NULL
. You do not copy this orNULL
terminate your newnewArgvs
. E.g. https://stackoverflow.com/questions/16418932/is-argvargc-equal-to-null-pointerThe Standard (C99 5.1.2.2.1p2) mandates that:
If they are declared, the parameters to the main function shall obey the following constraints:
— The value of argc shall be nonnegative.
— argv[argc] shall be a null pointer.
Note the last point. I doubt it's that, but worth a try on your new copy?
-
@Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):
strcpy(newArgvs[0], argv[0]);
This could easily overflow. What's the result of
strlen(argv[0])
? -
@Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):
the call to QApplication(argc, argv) happens in ICService::mfExec
Some code would be good...
You already posted a link with the solution but ignored it constantly - Q(Core)Application takes a reference to anint
so the callers should pass this to. Otherwise there might be a dangling reference. But without code...wrt to your strange copy stuff (whyever you need to modify your command line - sounds like a strange hack for me):
std::vector<char*> newArgs; newArgs.push_back(argv[0]); newArgs.push_back(const_cast<char*>("-e")); for (int i = 1; i < argc; ++i) newArgs.push_back(argv[i]); argc += 1; ...mfParseArguments(argc, newArgs.data());
-
@kshegunov said in Segfault when calling QWidget::show (on Debian 9):
This could easily overflow. What's the result of
strlen(argv[0])
?I've added
std::cout << "strlen(argv[0]) = " << strlen(argv[0]) << std::endl;
right before the
strcpy
statement and the result is 14. Knowing thatnewArgvs[0]
was allocated withnew char[256]
I would assume this is not causing trouble. -
@Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):
Some code would be good...
Sorry for not posting code here, @Christian-Ehrlicher, but my question is related to code I work on professionally and for as far as I know I am not allowed to share any code.
-
@Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):
allowed to share any code.
Then good luck. We can't guess your code...
Apart from this you already shared code.
-
@Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):
I would guess this is either a nullptr or not initialized. Build your app with debug information, go to stack frame 7 and print out the value of mpMainWindow .
I've added the
-g
option to our release build and when I run the application in gdb it now segfaults with the following call stack:user@debianvbox:~/SVN/PolarisRel/Apps$ gdb ./PolarisSlave GNU gdb (Debian 7.12-6) 7.12.0.20161007-git Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-linux-gnu". Type "show configuration" for configuration details. For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word"... Reading symbols from ./PolarisSlave...done. (gdb) r Starting program: /home/user/SVN/PolarisRel/Apps/PolarisSlave [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1". Program received signal SIGSEGV, Segmentation fault. strlen () at ../sysdeps/x86_64/strlen.S:106 106 ../sysdeps/x86_64/strlen.S: No such file or directory. (gdb) bt #0 strlen () at ../sysdeps/x86_64/strlen.S:106 #1 0x00007ffff3e101ed in XSetCommand () from /usr/lib/x86_64-linux-gnu/libX11.so.6 #2 0x00007ffff3e147f0 in XSetWMProperties () from /usr/lib/x86_64-linux-gnu/libX11.so.6 #3 0x00007ffff659007d in QWidgetPrivate::create_sys(unsigned long, bool, bool) () from /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4 #4 0x00007ffff6548769 in QWidget::create(unsigned long, bool, bool) () from /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4 #5 0x00007ffff6550697 in QWidget::setVisible(bool) () from /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4 #6 0x000055555594a1fd in QWidget::show (this=<optimized out>) at ../../ThirdParty/Qt/qt-install/include/QtGui/qwidget.h:497 #7 BSPPolarisSlave::mfRun (this=0x7fffffffe0e0, argc=<optimized out>, argv=<optimized out>, errormsg=...) at BSPPolarisSlave.cpp:443 #8 0x0000555555c010da in ICService::mfExec(int, char**, QString&, bool) () #9 0x0000555555bfd90e in ICService::mfParseArguments(int, char**, bool) () #10 0x000055555594dbb3 in BSPPolarisSlave::mfParseArguments (this=0x7fffffffe0e0, argc=2, argv=0x7fffffffe258) at BSPPolarisSlave.cpp:659 #11 0x000055555592a3ad in main (argc=1, argv=0x7fffffffe258) at BSPPolarisSlaveMain.cpp:71 (gdb) f 7 #7 BSPPolarisSlave::mfRun (this=0x7fffffffe0e0, argc=<optimized out>, argv=<optimized out>, errormsg=...) at BSPPolarisSlave.cpp:443 443 mpMainWindow->show(); (gdb) p mpMainWindow $1 = (BSPPolarisSlaveMainWindow *) 0x555556627c40
Some things I noticed are:
mpMainWindow
is notnullptr
.- In the call to
BSPPolarisSlave::mfRun
argc
andargv
are marked as 'optimized out'... and similarly, in the call toQWidget::show
, thethis
parameter is also 'optimized out'. I have not much experience with gdb (most of the time, I debug in the Visual Studio debugger)... but could this 'optimizing out' be the problem?
-
@Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):
mpMainWindow is not nullptr
are you sure it is initialised then ? gdb, in contrast to its MSVC equivalent, does no null initialisations during debug runs. So an uninitialised pointer is very rarely a nullptr
-
@J-Hilk said in Segfault when calling QWidget::show (on Debian 9):
are you sure it is initialised then ? gdb, in contrast to its MSVC equivalent, does no null initialisations during debug runs. So an uninitialised pointer is very rarely a nullptr
For as far as I can see yes, because right before the call to
show()
, the pointer is initialized:mpMainWindow = new BSPPolarisSlaveMainWindow(this, windowsCaption, 0, true, Qt::Window | Qt::WindowTitleHint | Qt::WindowSystemMenuHint); connect(mpApplication, SIGNAL(lastWindowClosed()), mpApplication, SLOT(quit())); mpMainWindow->show();
-
@Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):
Then good luck. We can't guess your code...
Apart from this you already shared code.
In the past on this forum, I've had good answers leading to a solution even without sharing code. I do believe that's possible :-)
And you are right: I have shared some code snippets. That is indeed not consistent with what I wrote, but I am somehow assuming that I am allowed to share small, non meaningful snippets of code that do not reveal any company secrets, if that can help us get to a solution quicker. I hope no one in our company will blame me for that... Finding the right balance between what you can share in order to get to a solution quicker is not always easy, but I try to find that balance.
-
Some more info on this problem:
- It is only a release build on Debian 9 that segfaults. As mentioned earlier, the debug build on Debian 9 runs fine.
- Release builds and debug builds on Debian 8 and Red Hat Enterprise Linux 8.5 run fine!
-
@Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):
wrt to your strange copy stuff (whyever you need to modify your command line - sounds like a strange hack for me):
std::vector<char*> newArgs; newArgs.push_back(argv[0]); newArgs.push_back(const_cast<char*>("-e")); for (int i = 1; i < argc; ++i) newArgs.push_back(argv[i]); argc += 1; ...mfParseArguments(argc, newArgs.data());
I totally agree that that modification of the command line is strange. Note that this was not my idea, but I inherited this legacy code from my predecessors :-(
I tried your suggestion usingstd::vector
instead of using an array ofchar*
, but that also didn't solve the segfault. -
@Bart_Vandewoestyne
Just so you know. Your segfault emanates from this line: https://code.woboq.org/kde/qt4/src/gui/kernel/qwidget_x11.cpp.html#804XSetWMProperties(dpy, id, 0, 0, qApp->d_func()->argv, qApp->d_func()->argc, &size_hints, &wm_hints, &class_hint);
(Doubtless some sort of X set window manager properties on start up?) It's on a
strlen()
from there, so presumably some element inqApp->d_func()->argv
is wrong. So you're still on theargv
issue. Try to print out everything in the lastargv
you pass on. -
@Bart_Vandewoestyne new debian, huh. New/updated compiler then as well?
I assume you have tried the release build with
-O0
? -
@J-Hilk or run it with valgrind (compile with -O2 and -g)