sage
sage

Reputation: 5514

Why might c++ application evaluate expression incorrectly?

As I was writing this question, it dawned on me that we are possibly using two versions of Qt due to embedded and non-embedded application builds. We are all using gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4). My build environment is:

QMake version 2.01a
Using Qt version 4.7.3 in /usr/local/Trolltech/QtEmbedded-4.7.3/lib

At least one of my colleagues is using:

QMake version 2.01a
Using Qt version 4.7.2 in /usr/lib

Two of my colleagues have run into issues when they made stand-alone applications that use my computational library. Our primary application and my stand-alone unit test application work fine and my investigations found no issues with my code. I have concluded that there must be some fundamental issue with the build environment or compiler because in both cases we isolated erratic/nonstandard behavior. The case I isolated is as follows:

void className::functionName(float newDeltaTime)
{
    float zero_ = 0;
    std::cout << "newDeltaTime: " << newDeltaTime << std::endl;
    std::cout << "zero_: " << zero_ << std::endl;
    std::cout << "newDeltaTime > zero_: " << (newDeltaTime > zero_) << std::endl;
    std::cout << "newDeltaTime > zero_: " << (newDeltaTime > zero_) << std::endl;
    std::cout << "newDeltaTime > zero_: " << (newDeltaTime > zero_) << std::endl;
...

This outputs:

newDeltaTime: 0.2
zero_: 0
newDeltaTime > zero_: 0
newDeltaTime > zero_: 1
newDeltaTime > zero_: 1

With gdb (as run by QtCreator) we see values of the variables that are correct - uncorrupted - at each line. That is what was really strange to me. There is no change to the variables as shown by the debugger, yet the exact same expression yields a different value the second time.

Originally, I had some error checking that said if(newDeltaTime > 0) { //do something } else { //log and throw } and my boss showed me code that was throwing the exception with the value 0.2 (shown above). I could not figure out the issue. When I added logging, the code started working, but I noticed the logging had the incorrect boolean expression value. Finally, I thought to log the expression multiple times, resulting in the output shown above.

I feel like the ground is shaky - what could cause this to happen? Everything compiles without errors and if we evaluate the expression twice and use the result the second time, then it seems to work fine. I'm familiar with voting logic when single event upsets may occur (space radiation hitting circuitry and compromising logic), but I shudder to think it is necessary here...

Upvotes: 1

Views: 294

Answers (1)

Employed Russian
Employed Russian

Reputation: 213556

what could cause this to happen?

The only things that I can think of are

  • a mis-match between the compiler (headers) and libstdc++ that you are using.
  • a signal processing code that corrupts stack

If the output you listed is always repeatable, then the second reason can't be it, and only the first reason remains.

If you observe this behavior with non-optimized code, the way I would approach this: set a breakpoint in GDB on the first std::cout << "newDeltaTime > zero_: " <<... line, and verify that after the execution of that line newDeltaTime is no longer 0.2. Re-run again, this time setting a GDB watchpoint with watch *(float*)&newDeltaTime, and see exactly where the value is getting corrupted (presumably somewhere inside libstdc++).

If you only observe this with optimized code, things get trickier, and you'll need to know about ABIs and calling conventions before you can debug this effectively.

Upvotes: 2

Related Questions