我最近遇到的使用abs()的奇怪错误

发布于 2024-12-07 14:19:49 字数 1843 浏览 0 评论 0原文

我有 C++/C 混合代码,它是

在 Win-7 x32 上的 a) Visual C++ 2010 Express(免费版)上构建的。

b) 安装在 Windows-7 Home premium Edition x32 上的 Cygwin/Gcc 环境。 gcc版本3.4.4(cygming特殊,gdc 0.12,使用dmd 0.125)

c)Ubuntu 10.04 Linux-GCC版本4.4.3(Ubuntu 4.4.3-4ubuntu5)

我有一个代码如下(它是我的用户的成员函数)定义的类),它计算传递的对象 myhalf 的绝对值-

myhalf::myhalfabs(myhalf a)
{
    float tmp;   
    tmp = abs(a.value); //This abs is from math.h :-  float abs(float)
    return tmp;
}

这在 MS 中完美地按照预期工作 - Visual C++ 2010. -ve nos 的abs() 正确返回为具有相同值的+ve nos。 奇怪的是,当我在 b) Cygwin/gcc 环境 & 上构建此代码时c) 上面提到的 Linux-gcc 4.4.3,我得到了垃圾输出。因此启动了 gdb,经过大量的汗水和代码上的“二进制搜索方法”来确定它开始出错的地方,我点击了如上所示的这段代码:

tmp = abs(a.value);

它在 cygwin/gcc 下表现得很奇怪。

对于 -ve 个数字,abs() 返回 0(零)。搞什么??

然后作为解决方法,避免从 stdlib 调用abs(),并编写我自己的abs,如下所示:

myhalf::myhalfabs(myhalf a)
{
    float tmp;
    unsigned int tmp_dbg;
    // tmp = abs(a.value);
    tmp_dbg = *(unsigned int*)(&a.value);
    tmp_dbg = tmp_dbg & 0x7FFFFFFF;
    tmp = *(float*)(&tmp_dbg);

    return tmp;
}

这在 cygwin/gcc 和 cygwin/gcc 上运行良好; linux-gcc 和输出是根据需要的,当然它在 MS-Visual C++ 2010 上工作得很好。

这是我使用的 cygwin/gcc 和 linux-gcc 构建的整个 Makefile。如果有人怀疑那里有可疑之处:-

OBJS= <all my obj files listed here explicitly>

HEADERS= <my header files here>
CFLAGS= -Wall
LIBS= -lm
LDFLAGS= $(LIBS)

#MDEBUG=1
ifdef MDEBUG
CFLAGS += -fmudflap
LDFLAGS += -fmudflap -lmudflap
endif

myexe:    $(OBJS)
    g++ $(OBJS) $(LDFLAGS) -o myexe

%.o:    %.cpp $(HEADERS) Makefile
    g++ $(CFLAGS) -c $<

clean:
    rm -f myexe $(OBJS)

1] 这里发生了什么?这个奇怪的错误的根本原因是什么?

2] 我是否在 cygwin 上使用某些旧版本的 gcc,该版本存在已知错误或其他问题?

3] 这个函数 float abs(float) 是否已知已被弃用或有新版本取代它?

任何指针都是有用的。

I have C++/C mixed code which I build on

a) Visual C++ 2010 Express(Free version) on Win-7 x32.

b) Cygwin/Gcc environment installed on a Windows-7 Home premium edition x32. The gcc version 3.4.4 (cygming special, gdc 0.12, using dmd 0.125)

c) Ubuntu 10.04 Linux- GCC version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)

I have a code as below(Its a member function for my user defined class) which computes absolute value of the passed object myhalf-

myhalf::myhalfabs(myhalf a)
{
    float tmp;   
    tmp = abs(a.value); //This abs is from math.h :-  float abs(float)
    return tmp;
}

This is working perfectly as desired in MS - Visual C++ 2010. abs() of -ve nos were returned correctly as +ve nos having same value.
Strangely when I built this code on b) Cygwin/gcc environment & c) Linux-gcc 4.4.3 mentioned above, I was getting junk output. So fired up gdb, and after lot of sweat and 'binary-search approach' on the code to decide where it started going wrong, I hit this piece of code as shown above :

tmp = abs(a.value);

which was behaving strangely under cygwin/gcc.

For -ve numbers abs() was returning 0(zero). WTF??

Then as a work around, avoided calling abs() from stdlib, and coded my own abs as below:

myhalf::myhalfabs(myhalf a)
{
    float tmp;
    unsigned int tmp_dbg;
    // tmp = abs(a.value);
    tmp_dbg = *(unsigned int*)(&a.value);
    tmp_dbg = tmp_dbg & 0x7FFFFFFF;
    tmp = *(float*)(&tmp_dbg);

    return tmp;
}

This worked fine on cygwin/gcc & linux-gcc and output was as desired, And of course it worked fine on MS-Visual C++ 2010.

This is the whole Makefile for the cygwin/gcc and linux-gcc builds, I use. Just if anyone supspects something fishy there:-

OBJS= <all my obj files listed here explicitly>

HEADERS= <my header files here>
CFLAGS= -Wall
LIBS= -lm
LDFLAGS= $(LIBS)

#MDEBUG=1
ifdef MDEBUG
CFLAGS += -fmudflap
LDFLAGS += -fmudflap -lmudflap
endif

myexe:    $(OBJS)
    g++ $(OBJS) $(LDFLAGS) -o myexe

%.o:    %.cpp $(HEADERS) Makefile
    g++ $(CFLAGS) -c 
lt;

clean:
    rm -f myexe $(OBJS)

1] What is going on here? What is the root cause of this strange bug?

2] Am i using some old version of gcc on cygwin which has this issue as known bug or something?

3] Is this function float abs(float) known to be deprecated or something with a newer version superseding it?

Any pointers are useful.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

熊抱啵儿 2024-12-14 14:19:50

首先,abs() 接受并返回一个int。您应该使用 fabs(),它接受并返回一个浮点值。

现在,您最终调用的 abs() 实际上是 GCC 内置的函数,它返回一个int,但显然接受一个float参数并在这种情况下返回0

First, abs() takes and returns an int. You should use fabs(), which takes and returns a floating-point value.

Now, the abs() you're ending up calling is actually a GCC built-in function, which returns an int, but apparently accepts a float argument and returns 0 in that case.

从此见与不见 2024-12-14 14:19:50

几乎可以肯定,在您的 MSVC 案例中,它正在获取 C++ abs 浮点重载(可能由于某种原因被带入全局命名空间)。然后在 g++ 中,它不会获取 C++ 版本(它不会隐式导入到全局命名空间中),而是会运行并返回一个 int 的 C 版本,然后将输出截断为零。

如果您#include 并使用std::abs,它应该可以在您的所有平台上正常工作。

Almost certainly what's happening is that in your MSVC case it's picking up the C++ abs float overload (which is probably being brought into the global namespace for some reason or other). And then in g++ it's NOT picking up the C++ version (which isn't implicitly imported into the global namespace) but the C version that works on and returns an int which is then truncating the output to zero.

If you #include <cmath> and use std::abs it should work fine on all your platforms.

长途伴 2024-12-14 14:19:49

math.h 具有 C 版本的 abs,它在 int 上运行。对于 C++ 重载使用 或对于 C 浮点版本使用 fabs()

math.h has the C version of abs which operates on ints. Use <cmath> for the C++ overloads or use fabs() for the C floating point version.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文