繁体   English   中英

G ++不会使用-O0编译我的源代码,但是会使用-O2 -DNDEBUG编译我的源代码,我该如何解决呢?

[英]G++ does not compile my source code with -O0 but it does with -O2 -DNDEBUG, how can I solve it?

我正在为ARM微控制器编写固件。 我建立了没有系统调用的交叉编译器,实际上我的RTOS(ChibiOS)提供了一个简单的系统调用实现。

我的所有代码都是用C语言编写的,除了某些部分,我仅使用C ++与Eigen库进行链接(线性代数的C ++模板库,它只是标头)。

如果我使用-O2 -DNDEBUG编译我的源示例代码(据我所知,使用NDEBUG,该代码将不需要assert()),那么一切都可以正常编译并且固件可以工作。

如果使用-O0编译源示例代码,则将具有以下内容:

Linking build/ch.elf
/home/noether/workspace/tool-chains/arm-none-eabi-4.6.2/lib/gcc/arm-none-eabi/4.6.2    /../../../../arm-none-eabi/lib/thumb/cortex-m4/libc.a(lib_a-abort.o): In function `abort':
/home/noether/workspace/tool-chains/summon-arm-toolchain/build/arm-none-eabi/thumb /cortex-m4/newlib/libc/stdlib/../../../../../../../gcc-4.6.2/newlib/libc/stdlib  /abort.c:63: undefined reference to `_exit'
/home/noether/workspace/tool-chains/arm-none-eabi-4.6.2/lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/thumb/cortex-m4/libc.a(lib_a-signalr.o): In function `_kill_r':
/home/noether/workspace/tool-chains/summon-arm-toolchain/build/arm-none-eabi/thumb/cortex-m4/newlib/libc/reent/../../../../../../../gcc-4.6.2/newlib/libc/reent/signalr.c:61: undefined reference to `_kill'
/home/noether/workspace/tool-chains/arm-none-eabi-4.6.2/lib/gcc/arm-none-eabi/4.6.2/../../../../arm-none-eabi/lib/thumb/cortex-m4/libc.a(lib_a-signalr.o): In function `_getpid_r':
/home/noether/workspace/tool-chains/summon-arm-toolchain/build/arm-none-eabi/thumb/cortex-m4/newlib/libc/reent/../../../../../../../gcc-4.6.2/newlib/libc/reent/signalr.c:96: undefined reference to `_getpid'
collect2: ld returned 1 exit status
make: *** [build/ch.elf] Error 1

我放-DNDEBUG没关系,我有相同的输出。 我也使用了这些标志-fno-exceptions和fno-rtti。 如果我不使用/链接Eigen库(唯一的C ++东西),即使使用-O0,g ++也会很好地编译源代码。

实际上,我实现了一个简单的_kill _getpid和_exit函数,并且代码进行了编译,但是代码从13KB变为130KB,并且崩溃了(也许我没有很好地编写这些函数)。

我想要的是如果我使用-O0,则从我的代码(中止等)中删除这些内容,因为使用-O2完成了(我想)。

非常感谢你。 如果您需要更多信息,请与我们联系。

这些引用几乎可以肯定是由于使用assert() 它将在失败时调用abort() ,从而将尝试引发一个信号(在此实现中使用kill() syscall)以中止该进程。 显然,如果您无法进行系统调用,则不可能这样做。

使用-DNDEBUG (就像您在优化版本中所做的一样)将解决此问题; 它会使assert()宏不生成任何代码,因此将没有对abort()引用。 优化级别本身不应该有任何区别。

另外,如果要保留断言,则可以实现自己的assert()宏,不需要任何系统调用。

您只需为那些缺少的系统调用实现存根并将它们链接到您的代码即可。 这样可以使链接程序保持安静,但是您可以使存根执行明智或有用的操作。 exit()可能会禁用中断并无限期循环或强制进行重置。 _kill()可能会挂接到您的RTOS中以终止线程,或仅调用_exit(),而_getpid()可能会返回一些虚拟值或RTOS线程ID。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM