[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Unexpected frexpf implementation used by MSVC9 in C++ mode
From: |
Michael Goffioul |
Subject: |
Unexpected frexpf implementation used by MSVC9 in C++ mode |
Date: |
Sun, 11 Mar 2012 18:30:19 +0000 |
Hi,
I'm trying to clarify a potential issue when using gnulib float math
functions like frexpf (and possibly others) with MSVC9. It all started
when compiling octave and getting link error because of duplicate
symbols like frexpf in libgnulib.la and octave code like Cell.cc. I
don't fully unserstand why I have duplicate symbol, but I think it's
related to the fact that frexpf is defined inline in MSVC math.h and
this is not well detected by the frexpf.m4.
To analyze further, I disassembled the 2 versions of frexpf and
compared them. In libgnulib.la, the code is as follows:
_frexpf:
00000000: 55 push ebp
00000001: 8B EC mov ebp,esp
00000003: 51 push ecx
00000004: 8B 45 0C mov eax,dword ptr [ebp+0Ch]
00000007: 50 push eax
00000008: D9 45 08 fld dword ptr [ebp+8]
0000000B: 83 EC 08 sub esp,8
0000000E: DD 1C 24 fstp qword ptr [esp]
00000011: E8 00 00 00 00 call _rpl_frexp
00000016: 83 C4 0C add esp,0Ch
00000019: D9 5D FC fstp dword ptr [ebp-4]
0000001C: D9 45 FC fld dword ptr [ebp-4]
0000001F: 8B E5 mov esp,ebp
00000021: 5D pop ebp
00000022: C3 ret
In octave code (like Cell.cc), the frexpf code is as follows:
_frexpf:
00000000: 55 push ebp
00000001: 8B EC mov ebp,esp
00000003: 51 push ecx
00000004: 8B 45 0C mov eax,dword ptr [ebp+0Ch]
00000007: 50 push eax
00000008: D9 45 08 fld dword ptr [ebp+8]
0000000B: 83 EC 08 sub esp,8
0000000E: DD 1C 24 fstp qword ptr [esp]
00000011: FF 15 00 00 00 00 call dword ptr [__imp__frexp]
00000017: 83 C4 0C add esp,0Ch
0000001A: D9 5D FC fstp dword ptr [ebp-4]
0000001D: D9 45 FC fld dword ptr [ebp-4]
00000020: 8B E5 mov esp,ebp
00000022: 5D pop ebp
00000023: C3 ret
As you can see, one version uses the frexp gnulib replacement, while
the other does not. The link error can be avoided by forcing MSVC to
accept duplicate symbols, but the problem is that there's a high
probability that the wrong version will be used.
For completeness, I've pasted below the pre-processed code of Cell.cc,
only the parts containing the string "frexp":
extern "C" {
...
__declspec(dllimport) double __cdecl frexp([SA_Pre(Null=SA_No)]
[SA_Pre(Deref=1,Valid=SA_Yes,Access=SA_Read)] double _X,
[SA_Pre(Null=SA_No,WritableElementsConst=1)]
[SA_Pre(Deref=1,Valid=SA_No)] int * _Y);
...
inline long double frexpl([SA_Pre(Null=SA_No)]
[SA_Pre(Deref=1,Valid=SA_Yes,Access=SA_Read)] long double _X,
[SA_Pre(Null=SA_No,WritableElementsConst=1)]
[SA_Pre(Deref=1,Valid=SA_No)] int *_Y)
{return (frexp((double)_X, _Y)); }
...
inline float frexpf([SA_Pre(Null=SA_No)]
[SA_Pre(Deref=1,Valid=SA_Yes,Access=SA_Read)] float _X,
[SA_Pre(Null=SA_No,WritableElementsConst=1)]
[SA_Pre(Deref=1,Valid=SA_No)] int *_Y)
{return ((float)frexp((double)_X, _Y)); }
...
}
...
extern "C++" {
...
inline float __cdecl frexp([SA_Pre(Null=SA_No)]
[SA_Pre(Deref=1,Valid=SA_Yes,Access=SA_Read)] float _X,
[SA_Pre(Null=SA_No,WritableElementsConst=1)]
[SA_Pre(Deref=1,Valid=SA_No)] int * _Y)
{return (frexpf(_X, _Y)); }
...
inline long double __cdecl frexp([SA_Pre(Null=SA_No)]
[SA_Pre(Deref=1,Valid=SA_Yes,Access=SA_Read)] long double _X,
[SA_Pre(Null=SA_No,WritableElementsConst=1)]
[SA_Pre(Deref=1,Valid=SA_No)] int * _Y)
{return (frexpl(_X, _Y)); }
...
}
...
extern "C" float frexpf (float x, int *expptr) ;
namespace gnulib { static float (*frexpf) (float x, int *expptr) =
::frexpf; } extern "C" int _gl_cxxalias_dummy;
...
extern "C" double rpl_frexp (double x, int *expptr);
namespace gnulib { double (*const frexp) (double x, int *expptr) =
::rpl_frexp; } extern "C" int _gl_cxxalias_dummy;
I think the problem is at least partially due to the inlined version
of frexpf provided by MSVC. This is not properly detected by
frexpf.m4, so gnulib provides a replacement. But then C++ code using
gnulib math.h will end up using the original inlined version from MSVC
when trying to use gnulib::frexpf, instead of the gnulib replacement.
I think MSVC copies the inlined frexpf in the object code and uses it
to assign gnulib::frexpf. This leads to the duplicate symbol
definition.
I'm not 100% sure of all this, but I have the impression this is
what's happening. Any comment?
Michael.
- Unexpected frexpf implementation used by MSVC9 in C++ mode,
Michael Goffioul <=