Opened 13 years ago

Closed 13 years ago

#222 closed defect (fixed)

Instantiating QApplication modifies floating point control word.

Reported by: rudi Owned by:
Priority: major Milestone: Qt 4.7
Component: QtGui Version:
Severity: high Keywords:
Cc:

Description

The following code:

int main(int argc, char *arg[])
{
  qDebug("FCW: %04x", _control87(0, 0) );

  QApplication  a(argc, argv);

  qDebug("FCW: %04x", _control87(0, 0) );

  ...
}

produces:

FCW: 037f
FCW: 0367

I.O.W., it enables floating point overflow and underflow exceptions. I don't think that this should happen.

Change History (9)

comment:1 Changed 13 years ago by rudi

Just to add: Qt 4.6.3 behaves identical.

comment:2 Changed 13 years ago by Dmitry A. Kuminov

Resolution: wontfix
Status: newclosed

This is a very old problem of OS/2. AFAIR, some GPI calls change FCW and then do not restore it back. There is a workaround for that in qdtoa() (there is a similar problem on Windows BTW). If we want to solve it globally we will have to write wrappers for all GPI (and probably Win*) calls which I consider as an overkill -- if you need a particular value of FCW for your code just go the qdtoa() way.

So unless you have a very good argument to do wrappers there is nothing we can do about this problem.

Thank you for reporting anyway.

comment:3 Changed 13 years ago by rudi

Resolution: wontfix
Status: closedreopened

Actually it's the call to WinCreateMsgQueue?() that is causing this particular problem. I strongly suggest to either add a local workaround to qeventdispatcher_pm.cpp or change API_FPU_CW_Wrappers.h.

For testing I did reset the FCW after WinCreateMsgQueue?(). This change made QtDecalarative? / QMLVIEWER work without the need for source code modifications as mentioned in #221 .

Version 0, edited 13 years ago by rudi (next)

comment:4 Changed 13 years ago by Dmitry A. Kuminov

Okay, recalled the whole wrappers thingy (#105). Yes, in this case the correct way is to modify API_FPU_CW_Wrappers.h (as your modifications to QtDeclarative are too hackish indeed). I will just save the FCW before each Win* call and then restore it afterwards. (Now the code simply disables the "division by zero" exception and leaves the under/overflow bits intact).

comment:5 Changed 13 years ago by rudi

Hehe, not more hackish than the original, I'd say ;-). They rely on the assumption that "double" is the largest member of the union which is also a questionable approach.

BTW, I suggest to change API_FPU_CW_Wrappers.h like this:

inline unsigned __fstcw(void)
{
    unsigned out;
    asm volatile ( "fstcw %0\n\t" : "=m" (out) );
    return out;
}

inline void __fldcw(unsigned in)
{
    asm volatile ( "fldcw %0\n\t" : : "m" (in) );
}

#define	__FPU_CW_SAVE		unsigned fcwState = __fstcw();
#define	__FPU_CW_RESTORE	__fldcw(fcwState);


inline BOOL APIENTRY __FPU_CW_WinCancelShutdown (HMQ hmq, BOOL fCancelAlways)
{
    __FPU_CW_SAVE
    BOOL ret = WinCancelShutdown (hmq, fCancelAlways);
    __FPU_CW_RESTORE
    return ret;
}
#define WinCancelShutdown __FPU_CW_WinCancelShutdown

...

IMHO, this generates the most efficient code. GCC's inline assembler is always fun...

Update: I had to change the code a bit to make it work correctly with GCC335. However, GCC4 produces better output.

Last edited 13 years ago by rudi (previous) (diff)

comment:6 Changed 13 years ago by abwillis

Could this also be added to qt3:
http://svn.netlabs.org/qt3/ticket/52

comment:7 Changed 13 years ago by rudi

I'm not sure if anyone is going to work on Qt3. However, I fixed the code snippet above to be compatible with the GCC that is used to compile Qt3.

comment:8 Changed 13 years ago by Silvan Scherrer

Andy, as we are not updating qt3 at all feel free to include your changes to this official tree. or just provide a custom qt3.
if you need svn write access let me know.

comment:9 Changed 13 years ago by Dmitry A. Kuminov

Resolution: fixed
Status: reopenedclosed

Fixed in r873. Thanks for finding that out.

Note: See TracTickets for help on using tickets.