C++编译器O3优化下bool转jboolean校验函数失效问题咨询
问题成因
C标准明确规定bool类型的合法取值仅为0(对应false)和1(对应true)。如果被声明为bool类型的内存中存储了其他数值,对这块内存的访问直接属于未定义行为。
编译器开启优化时会默认遵守C标准约定,认为所有bool类型变量的取值永远只能是0或1。因此你编写的bool2jboolean函数在优化器看来完全冗余:既然输入的bool b本身只能是0或1,b ? JNI_TRUE : JNI_FALSE和直接返回(jboolean)b没有任何区别,整个函数会被优化为直接返回输入参数的二进制值,完全跳过判断逻辑。
你测试代码中将int类型的地址强转为bool*传入,本质就是构造了一个取值非法的bool对象,触发了未定义行为,才会出现不同优化等级下结果不一致的问题。
正确实现方案
你需要校验可能存在非法取值的bool内存,核心要避免直接访问非法bool对象触发未定义行为,因此不能直接对bool*解引用,需要先读取内存的原始二进制值再做判断,实现方式如下:
#include <stdint.h> #define JNI_FALSE 0 #define JNI_TRUE 1 typedef uint8_t jboolean; jboolean safe_bool_to_jni(const bool* b) { // 转为字节指针读取原始值,不会触发bool类型的取值假设 const uint8_t* raw_ptr = reinterpret_cast<const uint8_t*>(b); return (*raw_ptr != 0) ? JNI_TRUE : JNI_FALSE; }
这种实现没有直接解引用bool*获取bool值,而是以字节为单位读取原始内存,编译器无法对原始字节的取值做假设,也就不会把判断逻辑优化掉,只要原始字节非0就返回JNI_TRUE,为0返回JNI_FALSE,完全符合你的校验需求。
位运算实现和上述方案本质等价,不需要额外使用更复杂的位操作,上述写法已经可以稳定生效。
内容的提问来源于stack exchange,提问作者zjysdhr
相关产品推荐
相关产品推荐

