线程中的数学函数返回错误的值,使用android ndk

math functions in thread returning wrong values, with android ndk

本文关键字:使用 android ndk 错误 返回 函数 线程      更新时间:2023-10-16

我在尝试将代码移植到Android NDK时遇到了一个问题,这在iOS上做得很好。该代码渲染3D模型并使用openGL ES 1.1,因此它使用标准c数学库(包括math.h)执行许多计算。

下面是用于测试异常的代码片段:

double e;
e = sqrt(25);
assert(e == 5);
e = sqrt(16);
assert(e == 4);
e = sqrt(9);
assert(e == 3);
e = sqrt(4);
assert(e == 2);
e = sqrt(1);
assert(e == 1);
e = sqrt(0);
assert(e == 0);

这些断言在任何地方都可以正常工作,而下面这个:

int vec[10] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81};
int res[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
double d;
for (int i=0; i<10; i++) {
    d = sqrt(vec[i]);
    assert(d == res[i]);
}

在除主线程以外的任何线程上崩溃。例如,它返回0.37500000008731149作为sqrt(0),这就是For循环上的第一个断言失败的原因。

似乎问题在于使用变量内容的计算,而不是硬编码值的计算。这可能是关于不同线程上的内存映射的问题吗?我调试了它,打印了vec[I]的值,这些都是正确的。

在不同的线程中使用数学库有任何问题吗?你能给我另一个解释为什么它的行为如此奇怪吗?

编辑:我也看到了同样奇怪的行为与其他数学函数,如pow()和sin()。另外,我还尝试了sqrtf和powf。

d == res[i]

这是你的问题。除了比较双精度型和整型并且不知道哪一个将被强制转换为另一个类型之外,还可以用==操作符比较浮点数。

浮点数和双精度数的比较不是这样的,因为

4.00000000000001 == 4.0

将返回false,浮点运算不是完美的,像sqrt(16)这样的运算不一定返回正好4。

不使用==操作符,而是使用如下函数(我还没有测试过它是否可以编译)

bool AreEqual(double a, double b)
{
  return a < b + 0.00001 && a > b - 0.00001;
}

我终于得到了一些关于如何"解决"这个问题的结论,尽管我有点失去了为什么会发生这种情况。

我实际上正在编写一个链接到几个c++库的应用程序,这是iOS和Android应用程序之间的通用代码。当在这些库中执行数学计算时,数学返回那些错误的值。我相信这不是关于线程的问题,而是关于库和链接的作用域的问题。当我编译应用程序内的所有库时,问题消失了,因为这些是另一个CPP源。但是,这不是最好的方法,因为这会破坏库的模块化。我必须修正它,但那将是一个非常不同的问题。