禁用C++异常时IAR链接器运行时模型冲突错误的解决求助
我们开发一款嵌入式系统,无法使用C++异常,已在编译器/链接器设置中关闭了异常支持,但如下代码结构会触发IAR链接器错误:
示例代码
struct Bla { Bla():blup{3u}{} uint8_t blup; }; template<typename T, size_t N> struct Warp { T bla[N]; }; int32_t main() { Warp<Bla,2> bla{}; return 0; }
链接器错误信息
IAR ELF Linker V9.30.1.335/W64 for ARM Copyright 2007-2022 IAR Systems AB. Error[Li009]: runtime model conflict: Module iar_Raise.o(dlpprt6M_tl_nc.a) specifies that '__CPP_Exceptions' must be 'Used', but module main.o has the value 'Disabled'
当未定义自定义构造函数、显式默认构造函数或构造函数仅为空实现时,该错误不会出现。
补充追踪信息
移除链接库dlpprt6M_tl_nc.a及--no_library_search标志可消除错误,但不符合项目指定库的要求;映射文件显示该库仅需cxxabi.o而非iar_Raise.o。另一种方法是仅在链接器而非编译器中使用--no_exceptions标志,但会增大二进制文件体积且逻辑不合理。
完整编译链接命令
Compiling ../../../application/source/Startup/startup_stm32g071xx.s ... 'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/bin/iasmarm ../../../application/source/Startup/startup_stm32g071xx.s -o ../../../target/build/obj/Startup/startup_stm32g071xx.o -r --cpu Cortex-M0+ -E42 --fpu=none -g -M'<>'' Compiling ../../../application/source/main.cpp ... 'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/bin/iccarm --debug -DDEBUG_BUILD --align_sp_on_irq --char_is_unsigned --cpu=Cortex-M0+ -DSTM32G071xx -DUSE_FULL_LL_DRIVER --dlib_config 'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/inc/c/DLib_Config_Normal.h -e --error_limit 42 --fpu=none --no_system_include --nonportable_path_warnings -Oh --only_stdout --require_prototypes --c++ --no_exceptions --no_rtti --no_static_destruction --pending_instantiations 256 -I"../../../application/source" -I'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/inc -I'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/inc/c -I'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/inc/c/aarch32 -I'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/inc/cpp -c ../../../application/source/main.cpp -o ../../../target/build/obj/main.o --dependencies=m ../../../target/build/dep/main.d Linking ... 'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/bin/ilinkarm --no_library_search --config CNT_stm32g071xB.icf --cpu=Cortex-M0+ --entry __iar_program_start --entry_list_in_address_order --error_limit 42 --extra_init __iar_cstart_call_ctors --fpu=none --log call_graph,libraries,sections,unused_fragments --no_exceptions --no_free_heap --only_stdout --remarks --semihosting --vfe ../../../target/build/obj/main.o ../../../target/build/obj/Startup/startup_stm32g071xx.o -o ../../../target/output/demo.elf --map ../../../target/output/demo.map --call_graph ../../../target/output/demo.cgx --export_builtin_config ../../../target/output/demo.icf --log_file ../../../target/output/demo.llog 'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/lib/rt6M_tl.a 'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/lib/dlpprt6M_tl_nc.a 'C:\Program Files\IAR Systems\Embedded Workbench 9.1\arm'/lib/dl6M_tln.a
替换无异常版本的C++运行时库
dlpprt6M_tl_nc.a是IAR中启用异常支持的C++运行时库,应替换为对应无异常版本(通常命名含_none,比如dlpprt6M_tl_none.a),可在IAR安装目录的arm/lib文件夹中查找匹配的库文件,替换链接命令中的对应库路径。强制排除异常相关模块
在链接命令中添加--exclude iar_Raise.o参数,明确告诉链接器不要从dlpprt6M_tl_nc.a中引入该异常处理模块,因为映射文件显示仅需cxxabi.o,该模块并非必需。修改构造函数避免隐式异常依赖
当自定义构造函数包含初始化列表时,IAR编译器在模板实例化过程中可能隐式生成异常处理相关代码。可改用聚合初始化替代自定义构造函数:struct Bla { uint8_t blup = 3u; // 聚合初始化,无需构造函数 };或标记构造函数为
constexpr,让编译器生成无异常的初始化代码。确保编译与链接的异常设置完全一致
严格保证编译器(--no_exceptions)和链接器(--no_exceptions)都启用禁用异常的选项,避免代码生成与链接库的异常模型冲突,杜绝仅在链接器设置标志导致的体积增大问题。
内容的提问来源于stack exchange,提问作者Paul R.

