Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
arm和x86体系结构中的c/c++语言有什么不同_C++_C_X86_Arm - Fatal编程技术网

arm和x86体系结构中的c/c++语言有什么不同

arm和x86体系结构中的c/c++语言有什么不同,c++,c,x86,arm,C++,C,X86,Arm,我正在尝试将最初为x86体系结构编写的代码移植到arm 最初它是为msvc/win32开发的,代码中有很多bug,所以可能会有UB 当使用gcc编译时,代码在x86上工作,但在arm上它有不同的行为。它似乎在阵列中丢失了一些数据,并且武器切换不起作用。 它同时影响服务器库和客户端库 应用程序是单线程的,所以它不是同步问题 在arm上,默认情况下Char是无符号的,因此我将-fsigned Char添加到编译器标志中,但这并没有解决问题。arm和x86C代码之间还有什么区别 我试着在arm上用gc

我正在尝试将最初为x86体系结构编写的代码移植到arm

最初它是为msvc/win32开发的,代码中有很多bug,所以可能会有UB

当使用gcc编译时,代码在x86上工作,但在arm上它有不同的行为。它似乎在阵列中丢失了一些数据,并且武器切换不起作用。 它同时影响服务器库和客户端库

应用程序是单线程的,所以它不是同步问题

在arm上,默认情况下Char是无符号的,因此我将-fsigned Char添加到编译器标志中,但这并没有解决问题。arm和x86C代码之间还有什么区别

我试着在arm上用gcc和clang编译代码,两者并没有区别,所以这不是一个编译器错误

附言 我用gcc-4.9而不是4.8为x86编译代码,得到了相同的行为。 之后,我组合了两个编译器,发现问题出在net_encode.c中

到那时,塞巴斯蒂安·契瓦利埃发现

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); 
提示:

如果还没有,请启用尽可能多的警告-至少是墙。并修复所有警告

检查pragma pack或类似的pack数据结构,以及类似的从char*到int*等的强制转换,因为这些可能导致未对齐的访问问题


编辑:当然,不同的编译器会有不同的bug,这些bug可能会或不会对特定的编译器、处理器和代码组合产生影响。虽然不太可能出现叮当声,但也会出现同样的问题。

如果没有看到您的代码,几乎不可能说,但会尝试大致回答

x86和ARM之间的一个巨大区别是,大多数x86指令都是内部原子的,而ARM没有这样的东西——您必须明确地说,以独占方式执行这组指令。因此,如果您有由多个线程更新的数据,您可能会受到影响

个别指令的行为方式也存在差异。在不知道代码的情况下,很难说它是否会影响代码,但有一件事可能会影响到未对齐的访问,这在x86中是完全有效的,尽管不是最优的,但在ARM处理器上的大多数型号中都是无效的。因此,指针必须与它访问的项的大小对齐

当然,编译器中的代码生成是不同的,编译器可能根据输入代码做出不同的决定,因此最终生成的代码在各个方面的行为都不同。我不止一次想到的是参数函数调用的执行顺序:

func(func1(), func2()); 
请注意,func1或func2可以先执行。如果您依赖此类订购,您需要执行以下操作:

t1 = func1();
t2 = func2();
func(t1, t2); 
提示:

如果还没有,请启用尽可能多的警告-至少是墙。并修复所有警告

检查pragma pack或类似的pack数据结构,以及类似的从char*到int*等的强制转换,因为这些可能导致未对齐的访问问题


编辑:当然,不同的编译器会有不同的bug,这些bug可能会或不会对特定的编译器、处理器和代码组合产生影响。虽然叮当声不太可能也会带来同样的问题。

我不是这方面的专家,但我可以指出一些一般性的问题

首先,根据ARM的版本和设置,某些基元类型的大小、符号性和endianness可能不同于x86,尤其是x86_64。在这方面,编写良好的可移植代码永远不应该对这些方面做出任何假设。如果你需要特定的尺寸 和signedness,使用/header中的类型。而持久性也是你应该注意的

其次,正如Mats所提到的,ARM和x86之间最臭名昭著、改变行为的区别之一是内存模型的严格性。简言之,x86趋向于非常保守,因此本质上是安全的,或者至少是毫不奇怪的,而ARM则较弱,因此可能更快。这对于并发代码尤其重要。默认情况下,x86上的许多基本操作都是原子操作,并且有许多隐式的完整内存围栏可以保证总体一致性。默认情况下,这些保护机制在ARM上没有那么多,这可能会导致许多奇怪的行为

例如,许多幼稚的多线程代码会错误地使用易失性变量作为线程之间共享信息或信号的方式。在许多情况下,由于其保守的内存模型,这在x86上可以正常工作。但在ARM架构上,该代码可能已被破坏

最后,一般来说,不同的体系结构在某些操作上的行为略有不同。所有这些差异通常都属于标准中未定义的行为或实现定义的类别。这些是最难发现的bug,因为未定义的行为通常意味着在一个体系结构和编译器上会发生一件事情,这可能是正常的,但在另一个体系结构上,会发生其他事情,这可能是不正常的


有一些工具可以帮助您解决所有这些问题。主要工具是所谓的消毒剂。这些工具为您的运行时代码提供了工具,可以检查与此相关的各种问题,也就是说,您可以使用工作的x86代码运行这些工具,它们会向您指出一些危险的事情,这些事情可能会在ARM或其他地方表现出不同的行为。您可以尝试未定义的行为消毒剂,用于UB操作,线程消毒剂,用于数据争用和危险的跨线程内存访问,以及地址消毒剂,用于一般的内存调试,它们在Clang和GCC下都可用。我不知道这些工具是否有什么特别的功能可以帮助ARM,或者它们是否针对ARM,但至少,在将x86移植到ARM时,修复它们指出的任何问题都会非常有帮助。

我不是这方面的专家,但我可以指出一些一般性的问题

首先,根据ARM的版本和设置,某些基元类型的大小、符号性和endianness可能不同于x86,尤其是x86_64。在这方面,编写良好的可移植代码永远不应该对这些方面做出任何假设。如果需要特定的大小和签名,可以使用/header中的类型。而持久性也是你应该注意的

其次,正如Mats所提到的,ARM和x86之间最臭名昭著、改变行为的区别之一是内存模型的严格性。简言之,x86趋向于非常保守,因此本质上是安全的,或者至少是毫不奇怪的,而ARM则较弱,因此可能更快。这对于并发代码尤其重要。默认情况下,x86上的许多基本操作都是原子操作,并且有许多隐式的完整内存围栏可以保证总体一致性。默认情况下,这些保护机制在ARM上没有那么多,这可能会导致许多奇怪的行为

例如,许多幼稚的多线程代码会错误地使用易失性变量作为线程之间共享信息或信号的方式。在许多情况下,由于其保守的内存模型,这在x86上可以正常工作。但在ARM架构上,该代码可能已被破坏

最后,一般来说,不同的体系结构在某些操作上的行为略有不同。所有这些差异通常都属于标准中未定义的行为或实现定义的类别。这些是最难发现的bug,因为未定义的行为通常意味着在一个体系结构和编译器上会发生一件事情,这可能是正常的,但在另一个体系结构上,会发生其他事情,这可能是不正常的

有一些工具可以帮助您解决所有这些问题。主要工具是所谓的消毒剂。这些工具为您的运行时代码提供了工具,可以检查与此相关的各种问题,也就是说,您可以使用工作的x86代码运行这些工具,它们会向您指出一些危险的事情,这些事情可能会在ARM或其他地方表现出不同的行为。您可以尝试未定义的行为消毒剂,用于UB操作,线程消毒剂,用于数据争用和危险的跨线程内存访问,以及地址消毒剂,用于一般的内存调试,它们在Clang和GCC下都可用。我不知道这些工具是否有什么特别的东西可以帮助ARM,或者它们是否甚至针对ARM,但至少,修复它们在x86上指出的任何问题在将其移植到
RM.

在一些塑料制品中,这并不是一个特别有用的问题描述,它变得非常疯狂。你必须更具体一些。查尔在C和C++中默认为未签名。如果没有显式指定为无符号,则所有其他整数类型都是有符号的。不要依赖于字符的有符号性。如果你看到人们在Stack Oveflow上对你可以和不可以假设的东西变得迂腐,那是因为他们试图保护你不受发疯的影响。在x86上它工作得很好,而在arm上的武器开关在服务器hlsdk和客户端xashxt代码中都不能正常工作。我找不到代码中不好的部分,因为我不知道什么地方会出错。你真的需要把问题分解成可管理的东西。代码的哪一部分以什么方式中断?这需要您做出一些努力,通过跟踪/记录和/或在调试器中运行代码,并跟踪实际问题。如果与网络数据包有关,我猜这是在使用未对齐的内存,但可能还有很多其他原因。在某些情况下,这并不是一个特别有用的问题描述。你必须更具体一些。查尔在C和C++中默认为未签名。如果没有显式指定为无符号,则所有其他整数类型都是有符号的。不要依赖于字符的有符号性。如果你看到人们在Stack Oveflow上对你可以和不可以假设的东西变得迂腐,那是因为他们试图保护你不受发疯的影响。在x86上它工作得很好,而在arm上的武器开关在服务器hlsdk和客户端xashxt代码中都不能正常工作。我找不到代码中不好的部分,因为我不知道什么地方会出错。你真的需要把问题分解成可管理的东西。代码的哪一部分以什么方式中断?这需要您做出一些努力,通过跟踪/记录和/或在调试器中运行代码,并跟踪实际问题。如果这与网络数据包有关,我猜它使用的是未对齐的内存,但可能还有很多其他的东西。