一个arm平台C++工程段md5错误的排查

Posted 李迟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个arm平台C++工程段md5错误的排查相关的知识,希望对你有一定的参考价值。

某 arm 工控机在试点测试时发现某数据文件无法下载。经几天时间,解决了问题,虽然没有很难的技术问题,但过程还是值得记录的。

起因

最近(几个月之前),收到反馈,某 arm 工控机在试点测试时发现某数据文件无法下载。经查,是 md5 源码文件的宏定义没有使用正确造成的,改正问题即解决。

排查及解决

问题定位

搭建模拟环境,复现问题。经测的确存在问题。查看日志发现文件的 md5 和记录的值不一致,因此无法成功下载。

保持环境相同,改用 x86 版本程序,能下载成功。

对比两者 md5 模块代码,完全一样(注:此处不应一样)。

添加调试代码,在函数内部输出 md5 值,同时在命令行中使用md5sum确认实际值。经测,只要是 arm 平台,下载的 md5 与命令行的结果不同。

后面,发现 md5 模块代码与 github这个仓库 较相近(最原始出版找不到),但在头文件global.h对一些类型做了些宏定义的修改。

github 仓库代码:

/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;

/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;

/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;

工程代码:

/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;

/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;

/* UINT4 defines a four byte word */
#if defined __amd64
typedef unsigned int UINT4;
#else
typedef unsigned long int UINT4;
#endif

问题出在UINT4的长度上,个人认为github 仓库的代码没有考虑到系统位数,在 32 位系统上,使用unsigned long int无问题,但 64 位须用unsigned int,在移植时,没有考虑到这个地方,因此在 arm 64 位系统上,UINT4就变大了,因此计算的 md5 值就不正确。

解决方法

定义如下即可:

/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;

/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;

/* UINT4 defines a four byte word */
#if defined __amd64 || defined __aarch64__
typedef unsigned int UINT4;
#else
typedef unsigned long int UINT4;
#endif

小结

个人认为,系统位数和系统类型还是分开对待比较好。比如 x86 和 arm 是系统类型,x86 有 64 位和 32 位,arm 也有 64 位和 32 位。对于需区分数值类型的,可以用标准的uint32_t一类关键字,能避免系统位数带来的问题。

附:

不同系统执行gcc -E -dM - </dev/null的输出结果如下


重要的:
#define __unix__ 1
#define unix 1
#define __unix 1
#define __linux 1
#define __linux__ 1
#define linux 1
#define __INT32_MAX__ 2147483647
#define __gnu_linux__ 1
#define __GNUC__ 4

64位 arm:
#define __SIZEOF_LONG_DOUBLE__ 16
#define __SIZEOF_SIZE_T__ 8
#define __INTPTR_TYPE__ long int
#define __UINT16_TYPE__ short unsigned int
#define __SIZE_TYPE__ long unsigned int
#define __SIZEOF_LONG_LONG__ 8
#define __UINT64_C(c) c ## UL
#define __INT16_MAX__ 32767
#define __UINT64_MAX__ 18446744073709551615UL

#define __aarch64__ 1
#define __AARCH64EL__ 1

32位x86:
#define i386 1

#define __SIZEOF_SIZE_T__ 4
#define __INTPTR_TYPE__ int
#define __UINT16_TYPE__ short unsigned int
#define __SIZE_TYPE__ unsigned int
#define __UINT32_TYPE__ unsigned int
#define __SIZEOF_LONG_LONG__ 8

#define __INT8_MAX__ 127
#define __UINT8_MAX__ 255
#define __INT16_MAX__ 32767
#define __UINT16_MAX__ 65535
#define __INT32_MAX__ 2147483647
#define __UINT32_MAX__ 4294967295U
#define __INT64_MAX__ 9223372036854775807L
#define __UINT64_MAX__ 18446744073709551615UL


64位 x86:
#define __x86_64 1
#define __amd64 1
#define __SIZEOF_SIZE_T__ 8
#define __INTPTR_TYPE__ long int
#define __UINT16_TYPE__ short unsigned int
#define __SIZE_TYPE__ long unsigned int
#define __UINT32_TYPE__ unsigned int
#define __SIZEOF_LONG_LONG__ 8

以上是关于一个arm平台C++工程段md5错误的排查的主要内容,如果未能解决你的问题,请参考以下文章

一个生产环境C++工程段错误的排查

一个生产环境C++工程段错误的排查

ROS/c++常见段错误以及排查

一个C++工程内存泄漏问题的排查及重现工程

一个C++工程CPU占用100%问题的排查

一个C++工程CPU占用100%问题的排查