OpenModelica生成代码函数传参异常(仅开启优化时触发)
解决OpenModelica生成C代码在GCC优化下的__OMC_DIV_SIM异常问题
问题梳理
先把你的问题再明确下,方便后续针对性排查:
- 使用OpenModelica 1.13.0-dev生成C代码
- 编译环境:CentOS 6.9 32位系统,GCC 4.4.7(受限制无法升级)
- 异常触发条件:仅在开启
-O1及更高优化等级时,调用__OMC_DIV_SIM函数传入数据会出现异常;-O0模式下运行完全正常 - 已获取
-O0模式下的gdb回溯信息:threadData=0x83bb7e0, a=0.900000000000000...
排查思路与解决办法
结合我处理老旧GCC版本和模型生成代码问题的经验,给你几个可行的方向:
给__OMC_DIV_SIM单独禁用优化
GCC 4.4.7在32位环境下的浮点数优化确实存在一些已知的小bug,尤其是涉及函数参数传递的场景。你可以直接给这个函数添加属性,强制它用-O0编译,不影响其他代码的优化效果:
在生成的C代码中找到__OMC_DIV_SIM的定义,加上__attribute__((optimize("O0"))):__attribute__((optimize("O0"))) void __OMC_DIV_SIM(threadData_t *threadData, real a, /* 其他参数 */) { // 函数原有实现 }如果不想修改生成的代码,也可以在编译时单独给该函数所在的文件指定
-O0,其他文件保持-O1:# 其他文件用-O1编译 gcc -O1 -c src/other_module.c # 包含__OMC_DIV_SIM的文件用-O0编译 gcc -O0 -c src/div_sim_module.c对比优化前后的参数传递差异
优化模式下GCC会调整寄存器分配和参数传递逻辑,可能导致浮点数参数在传递时出现偏差。你可以:- 在
-O1模式下调试,虽然优化后变量查看会有一定限制,但可以在__OMC_DIV_SIM函数入口处添加临时打印语句,输出传入的a值:
对比printf("Enter __OMC_DIV_SIM: a = %.18lf\n", a);-O0和-O1下的输出结果,看参数值是否被篡改。 - 检查
real类型的定义,确认它在生成的代码中是否对应double,是否存在隐式类型转换导致的精度丢失(比如32位环境下float和double的存储差异)。
- 在
检查OpenModelica生成代码的未定义行为
有些代码在-O0下因为内存布局的原因不会触发问题,但优化后会暴露未定义行为。你可以:- 查看
__OMC_DIV_SIM的实现代码,排查是否存在使用未初始化变量、指针越界、对同一变量的非法重定义等问题。 - 尝试简化你的模型,去掉非核心模块后重新生成代码,看问题是否消失,逐步定位是模型的哪个部分导致代码生成异常。
- 查看
临时绕过方案
如果暂时没时间深挖根本原因,最快速的办法就是给包含__OMC_DIV_SIM的代码文件单独用-O0编译,先保证功能正常,后续再慢慢排查问题根源。
内容的提问来源于stack exchange,提问作者bl4ckb0ne
相关产品推荐
相关产品推荐

