最近在尝试用树莓派控制海康机器人的相机,采用JAVA技术栈,发现相同的SDK接口函数
int MV_CC_SaveImageEx2(
IN void* handle,
MV_SAVE_IMAGE_PARAM_EX *pSaveParam
);
,用JNI调用OK,用JNA调用就
经过几天艰苦的定位,推测是因为MV_SAVE_IMAGE_PARAM_EX里的MvGvspPixelType枚举字段为8字节,而JNA分配的native内存为4字节,从而引发问题。
为什么树莓派这么个armv71
平台,其枚举类型会出现8字节的size?老实说我目前也不知道原因,不过我想先记录下异常现象。
复现异常
为了方便说明问题,将MvGvspPixelType简化(已将无关的宏消除)成PixelType
#include <stdio.h>
enum PixelType{
MONO = -1,
RGB = 0x80000000
};
int main(){
printf("sizeof enum PixelType = %d\n", sizeof(enum PixelType));
printf("MONO = 0x%x\n", MONO);
printf("RGB = 0x%llx\n", RGB);
return 0;
}
运行输出结果
sizeof enum PixelType = 8
MONO = 0xffffffff
RGB = 0x80000000
继续实验
把末项的最高位改成0
如果将RGB的值改成0x40000000
,则是4
enum PixelType{
MONO = 0xffffffff,
RGB = 0x40000000
};
编译出现告警:
test.c: In function ‘main’:
test.c:10:24: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘int’ [-Wformat=]
printf("RGB = 0x%llx\n", RGB);
~~~^
%x
运行结果
sizeof enum PixelType = 4
MONO = 0xffffffff
RGB = 0x4fb5c8f32c7300
把首项由-1改成0xffffffff
如果将MONO的值改成0xffffffff
,则是4
enum PixelType{
MONO = 0xffffffff,
RGB = 0x80000000
};
编译出现告警:
test.c: In function ‘main’:
test.c:10:24: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘unsigned int’ [-Wformat=]
printf("RGB = 0x%llx\n", RGB);
~~~^
%x
运行结果
sizeof enum PixelType = 4
MONO = 0xffffffff
RGB = 0x4135c8d827f000
不给末项指定值
enum PixelType{
MONO = 0x-1,
RGB
};
编译报跟上一个相同的告警:
test.c: In function ‘main’:
test.c:10:24: warning: format ‘%llx’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘int’ [-Wformat=]
printf("RGB = 0x%llx\n", RGB);
~~~^
%x
运行结果也跟上一个相同:
sizeof enum PixelType = 4
MONO = 0xffffffff
RGB = 0x4625c48451b500
把首项由-1改成0xffffffff,同时不给末项指定值
enum PixelType{
MONO = 0xffffffff,
RGB
};
编译报错:
test.c:4:5: error: overflow in enumeration values
RGB
^~~
思考
目前看来,只有以下3个条件同时满足时,才会复现该异常:
- 前面有一项是-1
- 末项指定了值
- 末项指定的值最高位为1
因为枚举默认是在前一个指定值上加一,当前一个被指定的值为无符号整形的最大值时,下一项默认加一就会溢出,编译器检测到了,符合预期,很好
但是为什么指定-1就会出现上述奇怪现象?期待有人来解答;-)