![](/img/trans.png)
[英]is g++ buggy ? and clang++ too ? g++ compiled code with -O0 and -O1 options behaves differently the same is true for clang++ with -O0 and -O2
[英]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.