如何隔离臂装置上的故障?

时间:2015-10-22 15:21:50

标签: c++ arm rapidjson

我在Arm设备上使用rapidjson并在运行此代码时出现奇怪的行为。

    #include <document.h>
    using namespace std;

int main()
{
    const char json []="[{\"Type\":\"float\",\"val_param\" : 12.025 }]";

    rapidjson::Document d;

    if( d.Parse<0>( json ).HasParseError() ) {
     //ErrorCase
    }else{
        rapidjson:: Value& val_param    = d[0]["val_param"];
        double tmp_double1  = val_param.GetDouble(); 
        cout << tmp_double1 <<endl; // -9.2559641157289301e+61 instead of 12.025
    }

    return 0;
}

在对这个问题进行投票之前。您还需要什么信息?我真的不知道如何隔离这个错误。如果是因为嵌入式设备或者rapidjson而发生的。以及如何解决它。

==========================更新==================== ====================

设备是什么? http://www.keith-koep.com/de/produkte/produkte-trizeps/trizeps-iv-m-eigenschaften/

它有硬件FPU吗?它是ARMv5所以我不这么认为。

您使用的是哪些编译器和库(版本号/特定版本)? 您传递给编译器和链接器的选项是什么?

arm-linux-gnueabi-g++ -march=armv5te -marm -mthumb-interwork --sysroot=/usr/local/oecore-x86_64/sysroots/armv5te-linux-gnueabi

1 个答案:

答案 0 :(得分:2)

这看起来可能是RapidJSON中的一个未定义的行为类型错误。

由于您的目标是ARMv5,您可能使用的是使用旧版ARM FPA格式的软件浮点库(而不是后来使用IEEE754格式的VFP)。至关重要的是,FPA以奇怪的中端格式存储事物,其中64位双精度存储为两个小端字,但最重要的字首先存储。

(是的,big-endian ARM是另一个复杂的问题,但由于我没有看到armeb-*三元组或-mbig-endian选项,我故意忽略它任意位置)

将12.025视为IEEE754双倍:

64-bit value:             0x40280ccccccccccd.
little-endian byte order: cd cc cc cc cc 0c 28 40
as little-endian words:   0xcccccccd 0x40280ccc

现在采用FPA格式:

as little-endian words:   0x40280ccc 0xcccccccd
byte order:               cc 0c 28 40 cd cc cc cc

尝试将其解释为纯小端64位值会产生0xcccccccd40280ccc,恰好是IEEE754表示-9.255965e + 61。想象一下!

通过快速浏览代码,它可能严格地说是一个不兼容而不是bug,因为RapidJSON似乎明确假设IEEE754格式的浮点值。值得赞扬的是,即使the parsing code看起来很毛茸茸,我确实看到unions而不是打字指针。但是,即使它不依赖于未定义的行为,它仍然依赖于实现定义的行为(浮点类型的格式) ,遗憾的是,这个编译器的实现并不符合这种期望。