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 by rudi, 13 years ago

Just to add: Qt 4.6.3 behaves identical.

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

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 by rudi, 13 years ago

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 QtDeclarative / QMLVIEWER work without the need for source code modifications as mentioned in #221. I have not yet tried to revert the sources for QtCreator's QMLJS.DLL, but I suspect with this change it will work out of the box as well.

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

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

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 by rudi, 13 years ago

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 USHORT __fstcw(void)
{
    USHORT out;
    asm ( "fstcw %0\n\t" : "=m" (out) : : );
    return out;
}

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

#define	__FPU_CW_SAVE		USHORT 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...

Version 1, edited 13 years ago by rudi (previous) (next) (diff)

comment:6 by abwillis, 13 years ago

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

comment:7 by rudi, 13 years ago

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 by Silvan Scherrer, 13 years ago

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 by Dmitry A. Kuminov, 13 years ago

Resolution: fixed
Status: reopenedclosed

Fixed in r873. Thanks for finding that out.

Note: See TracTickets for help on using tickets.