2

While writing a program including qt for gui, I stumbled upon a problem, which can be reproduced with the minimum code below:

#include <iostream>
#include <QApplication>
#include <QSettings>

using namespace std;

int main(int argc, char ** argv) {
    QApplication *app;
    {
        int tmp_argc = argc;
        app = new QApplication(tmp_argc, argv);
    }
    QSettings settings("testvendor");
    cout<<"Num of arguments: "<<app->arguments().count()<<std::endl;
    return 0;
}

Running results in either core dump (in the call to QApplication::arguments) or Num of arguments: 0 which is obviously wrong.

If I instantiate app with app = new QApplication(argc, argv) (using unscoped variable with the count of arguments) OR remove the declaration/definition of settings - the program outputs Num of arguments: 1 as expected (any one of these changes is sufficient).

I use Qt 5.5 on Ubuntu, the project is cmake-based, the contents of CMakeLists.txt:

cmake_minimum_required(VERSION 3.3)
project(qtest)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(CMAKE_PREFIX_PATH /opt/Qt/6.5.1/gcc_64/)
find_package(Qt5Widgets REQUIRED)

set(SOURCE_FILES main.cpp)
add_executable(qtest ${SOURCE_FILES})
target_link_libraries(qtest Qt5::Widgets)
Cthulhu
  • 1,379
  • 1
  • 13
  • 25

2 Answers2

4

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

From QT 5 Documentation. Emphasis mine.

tmp_argc goes out of scope.

QApplication *app;
{
    int tmp_argc = argc;
    app = new QApplication(tmp_argc, argv);
} <-- BOOM!
user4581301
  • 33,082
  • 7
  • 33
  • 54
  • Damn it, I never would've thought they would require me to keep some int variable, it's just insane! Seeing how the qapplication is actually created in some method, I guess i'll have to pass it there by reference as well. – Cthulhu Feb 23 '16 at 00:26
  • Lol. Designer from hell rides again. Lets take an int as reference and crash and then write documentation about it! The reference(pointer) is maybe larger than the int value would be but hey - it will be fun to show those guys who is boss and tell them: "RTFM". – BitTickler Feb 23 '16 at 11:12
  • I can see use cases where the caller needs to know what the QApp did to the args list, so I get the reference. Only reason I can see storing the reference is if you want to alow the QApp and the containing program to manipulate the args list over the course of the program as opposed to front-loading the arguments collection. – user4581301 Feb 23 '16 at 15:41
  • @Cthulhu "alow the QApp and the containing program to manipulate the args list" That's *precisely* what `QApplication` does. Remember that Qt has command line options of its own - they will get parsed and removed before your code gets to see the thus-modified argument list. Nothing insane about that. – Kuba hasn't forgotten Monica Feb 23 '16 at 16:26
1

Here's how to fix it, in line with requirements given in the documentation of QCoreApplication constructor:

// https://github.com/KubaO/stackoverflown/tree/master/questions/app-args-35566459
#include <QtCore>
#include <memory>

std::unique_ptr<QCoreApplication> newApp(int & argc, char ** argv) {
   return std::unique_ptr<QCoreApplication>(new QCoreApplication{argc, argv});
}

int main(int argc, char ** argv) {
    std::unique_ptr<QCoreApplication> app(newApp(argc, argv));
    QSettings settings{"testvendor"};
    qDebug() << "Num of arguments: " << app->arguments().count();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313