我正在尝试将最初为 x86 架构编写的代码移植到 arm。
https://github.com/SDLash3D
本来是为msvc/win32开发的,代码有很多bug,所以可能有UB。
代码在使用 gcc 编译时在 x86 上运行,但在 arm 上它有不同的行为。它似乎丢失了一些数组中的数据,并且武器切换不起作用。
它影响了服务器和客户端库。
应用是单线程的,所以不是同步问题。
Char 在 arm 上默认是无符号的,所以我将 -fsigned-char
添加到编译器标志中,但它并没有解决问题。 arm 和 x86 c 代码之间还有哪些其他区别?
我尝试用 gcc 和 clang 在 arm 上编译代码,没有区别,所以这不是编译器错误。
附言
我用 gcc-4.9(而不是 4.8)编译了 x86 的代码并得到了相同的行为。
之后我结合了两个编译器,发现问题出在 net_encode.c 中。
到时候,sebastien chevalier 发现
iValue/= pField->乘数;
iValue *= pField->乘数;
当 iValue 为整数且 pField->multiplier==1.0f 有时会更改整数值。
可以通过在相乘之前添加检查 pField->multiplier != 1.0f 来解决这个问题。
如果没有看到您的代码,几乎不可能说出来,但会尝试一般性地回答。
x86 和 ARM 之间的一个巨大区别是大多数 x86 指令在内部是原子的,而 ARM 没有这样的东西——你必须明确地说“只执行这组指令”。因此,如果您有由多个线程更新的数据,这可能会打击您。
各个指令的行为方式也存在差异。在不知道你的代码做了什么的情况下,很难说它是否会影响你的代码,但可以命中的一件事是“未对齐访问”,它在 x86 中完全有效(尽管不是最优的),但无效(在大多数情况下型号)在 ARM 处理器上。因此指针必须与其访问的项目的大小对齐。
当然,这是编译器中不同的代码生成,它们可能会根据输入代码做出不同的决定,因此最终得到的代码在所有方面都有不同的行为。不止一次打动我的是“参数函数调用的执行顺序”:
func(func1(), func2());
请注意,func1()
或 func2()
可能会先执行。如果您依赖于此类排序,则需要执行以下操作:
t1 = func1();
t2 = func2();
func(t1, t2);
提示:
如果您还没有启用,请启用尽可能多的警告(至少是-Wall
)。并修复所有警告
检查 #pragma pack
或类似的“包数据结构”,并类似地从 char *
转换为 int *
等,因为这些可能导致未对齐的访问问题。
编辑:当然,不同的编译器会有不同的错误,这些错误可能会或可能不会对特定的编译器、处理器和代码组合产生影响。尽管不太可能的 clang 也给出了同样的问题。