G++不使用 -O0 编译我的源代码,但使用 -O2 -DNDEBUG 编译我的源代码,我该如何解决它?
我正在为 ARM 微控制器编写固件。我已经构建了没有系统调用的交叉编译器,实际上我的 RTOS (ChibiOS) 提供了一个简单的系统调用实现。
我的所有代码都是用 C 编写的,除了某些部分我只使用 C++ 与 Eigen 库(用于线性代数的 C++ 模板库,它只是标头)链接。
如果我使用 -O2 -DNDEBUG 编译源示例代码(据我所知,使用 NDEBUG 代码不需要断言()),一切都会编译正常并且固件可以正常工作。
如果我使用 -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 完成的(我猜)。
非常感谢。如果您需要更多信息,请告诉我。
I am writing a firmware for an ARM microcontroller. I have built the cross-compiler without syscalls, actually my RTOS (ChibiOS) provides a simple syscalls implementation.
All my code is written in C excepting some parts where I only use C++ for linking with Eigen library (a C++ template library for linear algebra, it is only headers).
If I compile my source example code with -O2 -DNDEBUG (as far as I know with NDEBUG the code won't need assert()) everything compiles fine and the firmware works.
If I compile my source example code with -O0 I have the following:
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
It does not matter if I put -DNDEBUG, I have the same output.
I am using those flags as well, -fno-exceptions and fno-rtti.
If I do not use/link the Eigen library (the only C++ stuff), g++ compiles the source fine even with -O0.
Actually, I implemented a simple _kill _getpid and _exit functions, and the code compiles, but the code goes from 13KB to 130KB, and It crashes (maybe I haven't written well those functions).
What I want is to remove this stuff from my code (abort, etc) if I use -O0, as it is done (I guess) with -O2.
Thank you very much. Let me know if you need more information.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这些引用几乎肯定是由于使用
assert()
造成的;失败时将调用 abort() ,进而尝试发出信号(在此实现中使用 Kill() 系统调用)来中止进程。显然,如果您无法进行系统调用,这是不可能的。使用
-DNDEBUG
构建(就像在优化版本中所做的那样)将解决此问题;它会导致assert()
宏不生成任何代码,因此不会引用abort()
。优化级别本身不应该产生任何影响。或者,如果您想保留断言,您可以实现自己的
assert()
宏,该宏不需要任何系统调用。These references are almost certainly due to using
assert()
; that will callabort()
on failure, which in turn will try to raise a signal (using thekill()
syscall in this implementation) to abort the process. Obviously, this isn't possible if you can't make syscalls.Building with
-DNDEBUG
(like you do in the optimised version) will fix this; it causes theassert()
macro to generate no code, so there will be no references toabort()
. The optimisation level itself shouldn't make any difference.Alternatively, if you want to preserve your assertions, you could implement your own
assert()
macro that doesn't require any syscalls.您可以简单地为那些缺少的系统调用实现存根并将它们链接到您的代码。这将使链接器保持安静,但您可能会让存根做一些明智或有用的事情。 exit() 可能会禁用中断并无限循环或强制重置。 _kill() 可能会挂接到您的 RTOS 中以终止线程,或者简单地调用 _exit(),并且 _getpid() 可能会返回一些虚拟值或 RTOS 线程 ID。
You could simply implement stubs for those missing syscalls and link them to your code. That will keep the linker quiet, but you might make the stubs do something sensible or useful. exit() might disable interrupts and loop indefinitely or force a reset. _kill() might hook into your RTOS to terminate a thread, or simply call _exit(), and _getpid() might return some dummy value or an RTOS thread ID.