【问题标题】:Getting SIGILL in float to fixed conversion将 SIGILL 浮动到固定转换
【发布时间】:2011-02-04 20:52:38
【问题描述】:

运行以下代码后,我收到了 SIGILL。我实在想不通它有什么问题。

目标平台是 ARM,我正在尝试移植一个已知库(其中包含此代码)

void convertFloatToFixed(float nX, float nY, unsigned int &nFixed) {
    short sx = (short) (nX * 32);
    short sy = (short) (nY * 32);

    unsigned short *ux = (unsigned short*) &sx;
    unsigned short *uy = (unsigned short*) &sy;

    nFixed = (*ux << 16) | *uy;
}

我们将不胜感激。

提前致谢

【问题讨论】:

  • 在 C++ 中,第一次使用 static_cast 这样的命名类型转换,第二次使用reinterpret_cast,例如:short sx = static_cast&lt;short&gt;(nX * 32);unsigned short ux = reinterpret_cast&lt;unsigned short&amp;&gt;(sx);
  • 我已将 SIGILL 的原因确定到最后一行,但不明白为什么。里面有什么问题吗?
  • 我猜测代码生成错误,将返回地址吹到堆栈上。该代码提供了大量的绳索以允许编译器自行挂起。从摆脱指针转换开始,一个简单的转换就可以了。
  • 实际上,当我尝试访问 sxsy 变量时,会抛出 SIGILL,所以我猜测浮点到整数的转换有问题。
  • 您是否通过注释掉代码来“精确定位”这一点?如果是这样,当您注释掉最后一行时,编译器(如果优化)将丢弃整个函数体。你能反汇编这个函数,并准确地显示是哪条指令(和当时的寄存器)导致了错误吗?然后应该非常明显出了什么问题。另外,这是哪个 ARM SoC?你可能有一辆马车:)

标签: c++ arm porting


【解决方案1】:

有些 ARM 处理器有硬件浮点,有些没有,所以有可能这个函数是为硬件浮点编译的,但你的平台缺少浮点单元,所以浮点指令会导致处理器报告非法指令。如果这是您的测试程序中的第一个浮点计算,那极有可能是问题所在。检查您平台的文档以查找您需要将哪个 -march 选项传递给 gcc,或者查看一些已经工作的程序使用的编译选项。

此函数没有定义的行为,并且没有指示所需行为是什么,很难提出改进建议。尝试这样的开始:-

void convertFloatToFixed(float nX, float nY, unsigned int &nFixed) {
    assert(nX * 32 < INT_MAX);
    assert(nY * 32 < INT_MAX);

    int sx = nX * 32;
    int sy = nY * 32;

    unsigned int ux = sx;
    unsigned int uy = sy;

    nFixed = (ux << 16) | uy;
}

我已经摆脱了指针强制转换,这(正如其他人指出的那样)违反了严格的别名规则。我还使用了int 而不是short。拥有short 自动变量通常没有意义,因为无论如何在计算之前它们已经扩大到ints。 (他们做得很好,因为将 short 移动 16 位不会很有用。)我添加了一些检查,以便您的调试版本可以确定浮点到整数的转换是否会溢出,这会导致未定义的行为。

【讨论】:

  • 我会接受您的回答,因为问题与我当时(大约 2 年前)正在测试的系统上缺少浮点单元有关
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-21
  • 2012-04-04
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多