记录C/C++库从32位机器向64为机器移植过程中导致的问题和解决方案

最近程序库从32为向64为机器移植后,在使用过程中出现了一些问题,其中包括上一篇中记录的由于va_list类型不一致导致程序core dump或者出现异常行为的原因,这篇文章记录一下库移植之后出现的小问题。持续更新…

问题一: unsigned long int类型长度不兼容并对其按位操作

一般情况下在32位和64位机器单纯使用该类型在不出现数字大小溢出的情况下一般不会出现问题。但是有一种情况需要特别注意,即当对该unsigned long int进行位操作时,此时的操作结果在32和64位机器的操作结果会不同而导致其他问题。

例如使用unsigned long int类型作为key对其按位进行加密或哈希时,这时的加密或哈希结果会出现问题。

解决方法

将unsigned long int类型换为uint32_t在64位机器上重新编译

问题二: 32位和64位默认对齐不同导致数据类型大小不同

在linux系统下,32位机器数据默认以4字节对齐,64为机器默认以8字节对齐。

看如下结构构体:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
struct Test{
int a;
char* data[0];
};
int main() {
std::cout << sizeof(Test) << std::endl;
Test t;
std::cout << "&t:" << &t << std::endl
<< "&t.a" << &t.a << std::endl
<< "&t.data:" << &t.data << std::endl;
return 0;
}

32位机器运行结果:

1
2
3
4
8
&t:0x7ffd49f978b0
&t.a0x7ffd49f978b0
&t.data:0x7ffd49f978b4

64位机器运行结果:

1
2
3
4
8
&t:0x7ffd49f978b0
&t.a0x7ffd49f978b0
&t.data:0x7ffd49f978b8

解决方案:

在声明结构体前面加上#pragma pack(1)或#pragma pack(4),强制改变结构体的对齐方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#pragma pack(4)
struct Test{
int a;
char* data[0];
};
int main() {
std::cout << sizeof(Test) << std::endl;
Test t;
std::cout << "&t:" << &t << std::endl
<< "&t.a" << &t.a << std::endl
<< "&t.data:" << &t.data << std::endl;
return 0;
}