Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Segfault when calling QWidget::show (on Debian 9)



  • I have a Qt 4.8.7 program that is built on Debian 9. We compile Qt from source. The program segfaults only in a release build.
    Debug build runs fine. After some debugging, I was able to figure out that the crash happens at the statement

    mpMainWindow->show();
    

    where mpMainWindow is a pointer to a class that has QMainWindow as its base class. Using gdb, I was able to get a call stack at the moment of the crash (using the release build). It looks as follows:

    user@debianvbox:~/SVN/PolarisRel/Apps$ gdb ./MyApplication
    ... cutting away some gdb intro output ...
    Reading symbols from ./MyApplication...(no debugging symbols found)...done.
    (gdb) r
    Starting program: /home/user/SVN/PolarisRel/Apps/MyApplication
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
    ... cutting away some program output ...
    
    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  0x000055555594a3ef in MyApplication::mfRun(int, char**, QString&) ()
    #7  0x0000555555c01d0a in ICService::mfExec(int, char**, QString&, bool) ()
    #8  0x0000555555bfe53e in ICService::mfParseArguments(int, char**, bool) ()
    #9  0x000055555594e617 in MyApplication::mfParseArguments(int, char**) ()
    #10 0x000055555592a43e in main ()
    (gdb)
    

    I'm a bit puzzled why I don't see the show() function in the call stack, as to me that seems the place where the crash occurs.

    Also interesting to know is that this same application does not crash in release mode when I build it on Red Hat Enterprise Linux 8.

    Any thoughts on how I can debug this further or what could be the problem? If ldd or strace output is required, please let me know.



  • @Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):

    I'm a bit puzzled why I don't see the show() function in the call stack, as to me that seems the place where the crash occurs.

    In the meanwhile, I have figured out why that is: in the Qt 4.8.7 source in include\QtGui\qwidget.h we have

    #ifndef Q_WS_WINCE
        inline void show() { setVisible(true); }
    #else
        void show();
    #endif
    

    and since on my Debian 9 Q_WS_WINCE is not defined, show() is immediately inlined with setVisible(true).


  • Lifetime Qt Champion

    @Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):

    mpMainWindow

    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 .



  • @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 can confirm that mpMainWindow is not nullptr: I've added an if-test for that and I print something to stdout if it is null. Nothing is printed, so it's definitely not null (not saying the pointer value is OK though...)

    Next to that, it seems that our problem is very similar to the one described at https://www.mathiaswestin.net/2014/05/solved-qt-segmentation-fault-on.html.


  • Lifetime Qt Champion

    @Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):

    Nothing is printed,

    Then you did something wrong. Also checking an invalid pointer for != nullptr will most likley evaluate to true. Please show us your code.



  • @Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):

    Next to that, it seems that our problem is very similar to the one described at https://www.mathiaswestin.net/2014/05/solved-qt-segmentation-fault-on.html.

    That's a very odd one! And unfortunately where it refers to http://www.qtcentre.org/archive/index.php/t-45135.html?s=ea17a4ab05c00533d49f938c1da47077, that post has gone bye-byes, so I can't look up what was claimed to be the exact issue....

    This issue about char **argv vs char *argv[] (https://www.mathiaswestin.net/2014/05/solved-qt-segmentation-fault-on.html) can (should) only be an issue if you actually do something with argv. Temporarily at least can you not use it (presumably you only pass it to QApplication? And then I don't see why its declaration in your main() should matter.... Or do you do something else with it?), to see whether that fixes?

    P.S.
    I see that post says the stack trace is

    6 QWidget::show qwidget.h 494 0x804fd0c 
    7 mgccis::shell::MainApplication::InitializeInterface mainapplication.cpp 29 0x804facc 
    8 main main.cpp 25 0x804efb0 
    

    What was that mgccis::shell::MainApplication::InitializeInterface?

    Meanwhile I see now you go MyApplication::mfParseArguments(int, char**) (), etc. It ends up calling your MyApplication::mfRun(int, char**, QString&) (). What does that do with argv?


  • Lifetime Qt Champion

    @JonB char **argv and char *argv[] is actually the same - the problem in this post was that Q(Core)Application needs int & - but this should not matter here since it's only a problem when you not instantiate Q(Core)Application in main().



  • @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 your MyApplication::mfRun(int, char**, QString&) (). What does that do with argv?

    Well, actually, in MyApplication::mfParseArguments(int argc, char** argv) the argv from main 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 that newArgvs is passed to ICService::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 to MyApplication::mfRun which calls QWidget::show that segfaults.


  • Lifetime Qt Champion

    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 and argv are passed to that single QApplication instance, and could that be the reason for a segfault when calling QWidget::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 in ICService::mfExec before the call to MyApplication::mfRun and is with the new argc and argv, where the new argc is one more than the old argc (passed to main), and the new argv has one element (-e) more than the old argv (that was passed to main).

    Is it troublesome if in a call to QApplication(newArgc, newArgv) we have that newArgc != argc and newArgv is not the same as argv, where argc and argv were the arguments passed to main?



  • @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 original argv had an extra element at the end: argv[argc] == NULL. You do not copy this or NULL terminate your new newArgvs. E.g. https://stackoverflow.com/questions/16418932/is-argvargc-equal-to-null-pointer

    The 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?


  • Moderators

    @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])?


  • Lifetime Qt Champion

    @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 an int 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 that newArgvs[0] was allocated with new 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.


  • Lifetime Qt Champion

    @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 not nullptr.
    • In the call to BSPPolarisSlave::mfRun argc and argv are marked as 'optimized out'... and similarly, in the call to QWidget::show, the this 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?

  • Moderators

    @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 using std::vector instead of using an array of char*, 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#804

            XSetWMProperties(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 in qApp->d_func()->argv is wrong. So you're still on the argv issue. Try to print out everything in the last argv you pass on.


  • Moderators

    @Bart_Vandewoestyne new debian, huh. New/updated compiler then as well?

    I assume you have tried the release build with -O0 ?


  • Lifetime Qt Champion

    @J-Hilk or run it with valgrind (compile with -O2 and -g)


  • Moderators

    @Christian-Ehrlicher never used valgrind before, as I usually don't do linux stuff. But I trust your expertise :D


    oh it also now supports macOS, maybe I should give it a try sometime soon than!



  • @J-Hilk said in Segfault when calling QWidget::show (on Debian 9):

    @Bart_Vandewoestyne new debian, huh. New/updated compiler then as well?

    Yes, due to the switch from Debian 8 to Debian 9, a new compiler as well. Debian 8 (where everything works) has

    dev@debian8:~$ g++ --version | head -1
    g++ (Debian 4.9.2-10+deb8u2) 4.9.2
    

    while Debian 9 (where the release build segfaults) has

    user@debianvbox:~$ g++ --version | head -1
    g++ (Debian 6.3.0-18+deb9u1) 6.3.0 20170516
    

    I assume you have tried the release build with -O0 ?

    I hadn't, but now I have ;-) And I have interesting news: when using -O0 the segfault is gone! From -O1 and further, we get the segfault.



  • @Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):

    @J-Hilk or run it with valgrind (compile with -O2 and -g)

    I have no experience with valgrind, but looks like a good suggestion so I will try and report back.



  • @Christian-Ehrlicher said in Segfault when calling QWidget::show (on Debian 9):

    @J-Hilk or run it with valgrind (compile with -O2 and -g)

    OK, so I compiled with -O2 and -g and ran my program through valgrind. This is what I got:

    user@debianvbox:~/SVN/PolarisRel/Apps$ valgrind ./PolarisSlave
    ==5165== Memcheck, a memory error detector
    ==5165== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
    ==5165== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
    ==5165== Command: ./PolarisSlave
    ==5165== 
    ==5165== Invalid read of size 8
    ==5165==    at 0x8B3B205: XSetCommand (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
    ==5165==    by 0x8B3F7EF: XSetWMProperties (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
    ==5165==    by 0x5EE707C: QWidgetPrivate::create_sys(unsigned long, bool, bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x5E9F768: QWidget::create(unsigned long, bool, bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x5EA7696: QWidget::setVisible(bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x4FE1FC: show (qwidget.h:497)
    ==5165==    by 0x4FE1FC: BSPPolarisSlave::mfRun(int, char**, QString&) (BSPPolarisSlave.cpp:443)
    ==5165==    by 0x7B50D9: ICService::mfExec(int, char**, QString&, bool) (in /home/user/SVN/PolarisRel/Apps/PolarisSlave)
    ==5165==    by 0x7B190D: ICService::mfParseArguments(int, char**, bool) (in /home/user/SVN/PolarisRel/Apps/PolarisSlave)
    ==5165==    by 0x501BB2: BSPPolarisSlave::mfParseArguments(int, char**) (BSPPolarisSlave.cpp:659)
    ==5165==    by 0x4DE3AC: main (BSPPolarisSlaveMain.cpp:71)
    ==5165==  Address 0xbe71780 is 0 bytes after a block of size 16 alloc'd
    ==5165==    at 0x4C2C93F: operator new[](unsigned long) (vg_replace_malloc.c:423)
    ==5165==    by 0x501A27: BSPPolarisSlave::mfParseArguments(int, char**) (BSPPolarisSlave.cpp:637)
    ==5165==    by 0x4DE3AC: main (BSPPolarisSlaveMain.cpp:71)
    ==5165== 
    ==5165== Invalid read of size 1
    ==5165==    at 0x4C2EDA2: strlen (vg_replace_strmem.c:454)
    ==5165==    by 0x8B3B1EC: XSetCommand (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
    ==5165==    by 0x8B3F7EF: XSetWMProperties (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
    ==5165==    by 0x5EE707C: QWidgetPrivate::create_sys(unsigned long, bool, bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x5E9F768: QWidget::create(unsigned long, bool, bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x5EA7696: QWidget::setVisible(bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x4FE1FC: show (qwidget.h:497)
    ==5165==    by 0x4FE1FC: BSPPolarisSlave::mfRun(int, char**, QString&) (BSPPolarisSlave.cpp:443)
    ==5165==    by 0x7B50D9: ICService::mfExec(int, char**, QString&, bool) (in /home/user/SVN/PolarisRel/Apps/PolarisSlave)
    ==5165==    by 0x7B190D: ICService::mfParseArguments(int, char**, bool) (in /home/user/SVN/PolarisRel/Apps/PolarisSlave)
    ==5165==    by 0x501BB2: BSPPolarisSlave::mfParseArguments(int, char**) (BSPPolarisSlave.cpp:659)
    ==5165==    by 0x4DE3AC: main (BSPPolarisSlaveMain.cpp:71)
    ==5165==  Address 0x50 is not stack'd, malloc'd or (recently) free'd
    ==5165== 
    ==5165== 
    ==5165== Process terminating with default action of signal 11 (SIGSEGV)
    ==5165==  Access not within mapped region at address 0x50
    ==5165==    at 0x4C2EDA2: strlen (vg_replace_strmem.c:454)
    ==5165==    by 0x8B3B1EC: XSetCommand (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
    ==5165==    by 0x8B3F7EF: XSetWMProperties (in /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0)
    ==5165==    by 0x5EE707C: QWidgetPrivate::create_sys(unsigned long, bool, bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x5E9F768: QWidget::create(unsigned long, bool, bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x5EA7696: QWidget::setVisible(bool) (in /home/user/SVN/PolarisRel/ThirdParty/Qt/qt-install/lib/libQtGui.so.4.8.7)
    ==5165==    by 0x4FE1FC: show (qwidget.h:497)
    ==5165==    by 0x4FE1FC: BSPPolarisSlave::mfRun(int, char**, QString&) (BSPPolarisSlave.cpp:443)
    ==5165==    by 0x7B50D9: ICService::mfExec(int, char**, QString&, bool) (in /home/user/SVN/PolarisRel/Apps/PolarisSlave)
    ==5165==    by 0x7B190D: ICService::mfParseArguments(int, char**, bool) (in /home/user/SVN/PolarisRel/Apps/PolarisSlave)
    ==5165==    by 0x501BB2: BSPPolarisSlave::mfParseArguments(int, char**) (BSPPolarisSlave.cpp:659)
    ==5165==    by 0x4DE3AC: main (BSPPolarisSlaveMain.cpp:71)
    ==5165==  If you believe this happened as a result of a stack
    ==5165==  overflow in your program's main thread (unlikely but
    ==5165==  possible), you can try to increase the size of the
    ==5165==  main thread stack using the --main-stacksize= flag.
    ==5165==  The main thread stack size used in this run was 8388608.
    ==5165== 
    ==5165== HEAP SUMMARY:
    ==5165==     in use at exit: 1,121,308 bytes in 9,104 blocks
    ==5165==   total heap usage: 22,310 allocs, 13,206 frees, 4,039,124 bytes allocated
    ==5165== 
    ==5165== LEAK SUMMARY:
    ==5165==    definitely lost: 2,944 bytes in 6 blocks
    ==5165==    indirectly lost: 13,190 bytes in 537 blocks
    ==5165==      possibly lost: 54,718 bytes in 437 blocks
    ==5165==    still reachable: 1,050,456 bytes in 8,124 blocks
    ==5165==         suppressed: 0 bytes in 0 blocks
    ==5165== Rerun with --leak-check=full to see details of leaked memory
    ==5165== 
    ==5165== For counts of detected and suppressed errors, rerun with: -v
    ==5165== ERROR SUMMARY: 5 errors from 2 contexts (suppressed: 0 from 0)
    Segmentation fault
    

    I'll try to decipher this myself, but if in the meanwhile someone more experienced with valgrind can point me in the right direction, that would be nice :-)


  • Moderators

    from my point of view, I would say the issue is with your strange string manipulation stuff.

    You have to be very careful, when working with stringliterals, it is super easy to run into undefined behaviour, when you try to modify them.


  • Lifetime Qt Champion

    @Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):

    by 0x501A27: BSPPolarisSlave::mfParseArguments(int, char**) (BSPPolarisSlave.cpp:637)

    This is where you have to take a look on. You do something wrong there for an argument.


  • Moderators

    Please provide the the line that @Christian-Ehrlicher mentioned; it's the call to mfExec.



  • OK, I think we're getting there... In ICBlackBoxBase::mfInitialize we call the ICBlackBoxBaseApplication constructor which calls the QApplication constructor with certain argc and argv arguments:

    ICBlackBoxBaseApplication::ICBlackBoxBaseApplication(int &argc, char** argv, ICBlackBoxBase* apApp)
    : QApplication(argc,argv), mpApp(apApp)
    {
    }
    

    Now let's see what argc and argv we are passing there. I've set a breakpoint right before the location where we call this constructor, and this is the call stack:

    (gdb) bt
    #0  ICBlackBoxBase::mfInitialize (this=0x7fffffffe0e0, argc=2, argv=0x5555565cd3d0, errormsg=...) at ICBlackBoxBase.cpp:101
    #1  0x0000555555c0101d in ICService::mfExec(int, char**, QString&, bool) ()
    #2  0x0000555555bfd86e in ICService::mfParseArguments(int, char**, bool) ()
    #3  0x000055555594db13 in BSPPolarisSlave::mfParseArguments (this=0x7fffffffe0e0, argc=2, argv=0x7fffffffe258) at BSPPolarisSlave.cpp:654
    #4  0x000055555592a3bd in main (argc=1, argv=0x7fffffffe258) at BSPPolarisSlaveMain.cpp:71
    

    As you can see, in main we have that argc is 1, but in ICBlackBoxBase::mfInitialize (the function from which we call the ICBlackBoxBaseApplication constructor, and thus also the QApplication constructor) we have that argc is 2 (since an extra -e argument was added). Now let's look at argv in both main and ICBlackBoxBase::mfInitialize. In main we have:

    (gdb) f 4
    #4  0x000055555592a3bd in main (argc=1, argv=0x7fffffffe258) at BSPPolarisSlaveMain.cpp:71
    71		return (polarisSlave.mfParseArguments(argc, argv));	
    (gdb) p argc
    $12 = 1
    (gdb) p argv[0]
    $13 = 0x7fffffffe53a "/home/user/SVN/PolarisRel/Apps/PolarisSlave"
    (gdb) p argv[argc]
    $14 = 0x0
    

    but in ICBlackBoxBase::mfInitialize we have:

    (gdb) f 0
    #0  ICBlackBoxBase::mfInitialize (this=0x7fffffffe0e0, argc=2, argv=0x5555565cd3d0, errormsg=...) at ICBlackBoxBase.cpp:101
    101	{
    (gdb) p argc
    $15 = 2
    (gdb) p argv[0]
    $16 = 0x5555565cf830 "/home/user/SVN/PolarisRel/Apps/PolarisSlave"
    (gdb) p argv[1]
    $17 = 0x5555565cf940 "-e"
    (gdb) p argv[argc]
    $18 = 0x20 <error: Cannot access memory at address 0x20>
    

    so there argv[argc] is not null! And now I have to find out why :-)



  • @Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):

    so there argv[argc] is not null! And now I have to find out why :-)

    Earlier I wrote:

    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 original argv had an extra element at the end: argv[argc] == NULL. You do not copy this or NULL terminate your new newArgvs. E.g. https://stackoverflow.com/questions/16418932/is-argvargc-equal-to-null-pointer
    — argv[argc] shall be a null pointer.

    It is not clear whether this matters or not. If code only uses argc to index up to argv[argc - 1] then it does not. If code does do something about looking at argv[argc] to check for nullptr then it does matter. If you have the source code where it goes wrong you may be able to delermine.



  • @Bart_Vandewoestyne said in Segfault when calling QWidget::show (on Debian 9):

    ICBlackBoxBaseApplication::ICBlackBoxBaseApplication(int &argc, char** argv, ICBlackBoxBase* apApp)
    : QApplication(argc,argv), mpApp(apApp)
    {
    }
    

    I have an alternative theory. Work with me on this one, please!

    I believe the BSPPolarisSlave & ICService classes are your own(?). This ICBlackBoxBaseApplication constructor calls QApplication(argc,argv) with argc, and especially argv, *with the values they have on entry to the constructor. However (I believe you are saying) something it then does alters argc, and especially argv, to add further arguments, right? Note in your traceback how argv has a different (pointer) value from BSPPolarisSlave::mfParseArguments() down to ICBlackBoxBase::mfInitialize() --- it has been changed.

    Now, I am unclear whether the original argv, with its strings, is being used from the original QApplication(argc,argv), and just possibly the value/strings array is no longer valid. But it may be what is used the very first time QWidget::show() is called (to do some X initialisations from any (potential) X-type command-line arguments passed to your Qt app. Remember that https://doc.qt.io/qt-5/qcoreapplication.html#QCoreApplication says

    Warning: The data referred to by argc and argv must stay valid for the entire lifetime of the QCoreApplication object. In addition, argc must be greater than zero and argv must contain at least one valid character string.

    I think you should find that QWidget::show() which is in BSPPolarisSlave::mfRun(). On the line above it do something about printing out Qt's idea of the command line arguments which were used during the earlier QApplication(argc,argv). I believe static QStringList QCoreApplication::arguments() accesses these. So qDebug() those before QWidget::show(), do they look good or garbled?

    Finally, the question is why/what are these classes altering argc/argvfor, apparently to add additional arguments? If these new arguments are intended to be seen by Qt then it looks like you should not be callingQApplication(argc,argv)` until after they have been modified to hold the new command line?



  • I have also found the following text on https://doc.qt.io/archives/qt-4.8/qapplication.html#details

    "Since the QApplication object does so much initialization, it must be created before any other objects related to the user interface are created. QApplication also deals with common command line arguments. Hence, it is usually a good idea to create it before any interpretation or modification of argv is done in the application itself."

    It worries me... I don' think we actually modify argv (but we do modify argc)... but we do create a newArgv that has one more command line argument and that newArgv together with the modified argc is what gets passed to QApplication later on...

    So in summary, I think this is what we do:

    1. Start from main with argc and argv.
    2. increment argc by one and create newArgv from argv (newArgv has one extra -e command line argument).
    3. Call the QApplication constructor with the incremented argc and newArgv...


  • @Bart_Vandewoestyne
    I know this. I suggested what you need to do, to the QWidget::show() in BSPPolarisSlave::mfRun()....



  • @JonB said in Segfault when calling QWidget::show (on Debian 9):

    @Bart_Vandewoestyne
    I know this. I suggested what you need to do, to the QWidget::show() in BSPPolarisSlave::mfRun()....

    Yes, thanks for that suggestion. I'll look into it. I guess we were both typing our replies at the same time, but you were the first to press the 'Submit' button :-) Stay tuned for more! :-)


Log in to reply