Strange error initializing a QApplication before using std::stod

208 views Asked by At

I'm receiving an unexpected behavior in my current project.

I use the DICOM library dcmtk to read information from some dicom files, and Qt to show the images.

During the information extraction, I have to convert fields of the format "<64bit float>\<64 bit float>" (Dicom Tag PixelSpacing). I split into 2 strings at "\" and convert the strings into a double. So far, everything works fine.

Well, almost: whenever I create a QApplication object before I convert the strings to doubles, it gives me integers instead of doubles.

The code looks like this:

// Faulty situation
Database db;

QApplication app(&argc, argv);
db.fill_from_source(source); // here i get ints instead of doubles

// Rearrange code and recompile:
Database db;
db.fill_from_source(source); // now it gets me doubles.

QApplication app(&argc, argv);

// The fill function looks like this (simplified)
void Database::fill_from_source(const Source& source){

    string s = source.get_pixel_spacing_string();
    vector<string> s2 = split(s, "\\");

    // get the double, that should not be integers!
    double a = stod(s2[0]);
    double b = stod(s2[1]);
}

It confuses me even more, that it does work stepping through the code using QtCreator and GDB. However, when I run the executable, I get integers again.

So I tracked the issue down to the stod operation: I get the right strings out of the DICOM file, but after stod the numbers after the dot are just truncated. Same behavior with stdlib's strtod

Does the QApplication allocation does something with the std::stod function? Since everything happens while runtime, I do not understand how.

Replacing stod with QString::toDouble resolves the issue...

I'am using gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04.3), GNU ld (GNU Binutils for Ubuntu) 2.24.

Other code dependencies include Eigen3, Boost.Python. The code is built using a CMake project with QtCreator as IDE.

Has anyone an idea where this problem comes from? Is this a Qt bug?

2

There are 2 answers

1
rocambille On

std::stod behaviour depends on the currently installed C locale.

According to cppreference:

During program startup, the equivalent of std::setlocale(LC_ALL, "C"); is executed before any user code is run.

As pointed by @peppe in the comments, during QApplication's construction setlocale(LC_ALL, ""); is called on Unix, thus altering std::stod.

You can store the locale and set it back as follows:

std::string backup(
    // pass a null pointer to query the current C locale without modifying it
    std::setlocale(LC_ALL, nullptr)
);

QApplication app(&argc, argv);

// restore the locale
std::setlocale(LC_ALL, backup.c_str());

EDIT:

After rereading documentation for QCoreApplication, there is a paragraph about locale settings in detailed description:

On Unix/Linux Qt is configured to use the system locale settings by default. This can cause a conflict when using POSIX functions, for instance, when converting between data types such as floats and strings, since the notation may differ between locales. To get around this problem, call the POSIX function setlocale(LC_NUMERIC,"C") right after initializing QApplication, QGuiApplication or QCoreApplication to reset the locale that is used for number formatting to "C"-locale.

However @J.Riesmeier provided an interessant answer as one of the DCMTK developers.

0
J. Riesmeier On

Being one of the DCMTK developers, i.e. the DICOM toolkit you use, I wonder why you don't retrieve the floating point values directly from the DICOM data element "Pixel Spacing", I mean instead of retrieving the entire character string (including the backslash separator) first and then converting its components to individual floating point numbers. That way, there would be no problem at all with the current locale settings.

By the way, because of the locale settings issue we've introduced our own locale-independent OFStandard::atof() helper function :-)