編譯優化:這些鍋俺不背!

在使用 KEIL 調試時,可能遇到很多莫名其妙的事情,比如有些位置無法斷點調試,有些變量無法查看,很多人第一反應就是:是不是編譯器優化級別太高導致的?

但是當你真正去查看編譯級別時,發現已經是最低優化級別了。

編譯優化表示:俺不背這個鍋!

那麼這又是怎麼回事?

問題一:爲什麼有些地方無法打斷點?

要搞清這個問題,我們首先要知道的是,調試器通過什麼來確定哪些地方可以打斷點,哪些地方不可以打斷點?

相信有經驗的道友已經想到了,就是通過 axf 文件。

很多資料都會告訴你,axf 文件除了代碼之外,還包含了調試信息,那麼這些調試信息又是什麼?

其中一點就是 C 源碼和彙編之間的對應關係。

只有當調試器(MDK)加載了這個axf文件,它才能知道哪些地方可以打斷點,這個斷點位置和C語言與彙編之間又有怎樣的聯繫。

所以MDK 每次進入調試模式時,除了會下載代碼到單片機中,同時還會加載 axf 文件到調試器,從而在源碼級別進行調試。

那麼回到原來的問題,哪些地方可以打斷點呢?

看到左邊的灰色部分了吧,只有灰色部分纔是可以打斷點位置,其他地方調試器並不承認有執行代碼。

由此,我們可以通過這點確定一個宏是否處於開啓狀態。

比如一個宏打印 LOG(),如果打印開啓的話,那麼旁邊一定是深灰色的,否則說明這行沒有代碼可以執行。

同時我們也可以由此確定你當前的 axf 文件是否是最新的。

比如有段代碼修改了,但你進入調試模式後發現灰色部分和實際不一致,比如像這樣:

那你要做的事情,首先就是編譯 –> 下載。其次纔是查看你的編譯優化級別是否正確。

編譯是爲了將修改更新到 axf 文件中,下載是爲了更新單片機的代碼,之後進入調試模式時,單片機的代碼和新加載的 axf 文件也就對應上了。

當然爲了簡單,魚鷹一般的做法是直接 編譯 –> 調試。當編譯完之後,因爲 MDK 檢測到 axf 文件已經更新,所以會自動重新下載新代碼到單片機中(這個功能是默認配置,當然也可以不下載),之後自動加載新 axf 文件到調試器,同時進入調試模式。

有些時候,你會發現能很快進入調試模式,就是因爲調試器檢測到 axf 文件沒有過更新,所以也就不會自動下載了,這樣就節省了很多時間。

所以這個鍋,很可能就是因爲修改了代碼而忘記編譯導致,該你自己背。

問題二:爲什麼有些變量無法通過 watch 查看?

真的是因爲優化級別太高導致的嗎?

遇到這種情況,首先看看你的代碼是不是太簡單了。

因爲這個函數代碼很簡單,局部變量只有一個 temp(同時不需要對這個變量取地址操作),而空閒寄存器有很多,所以編譯器直接將這個變量分配到寄存器中,這樣這個 temp 變量就是 R4 寄存器,這樣可以加快運行速度。

所以,這個鍋也不能由編譯優化來背,只能說是編譯器的正常行爲,只是你不瞭解罷了。

而當你的函數很複雜時(或者明確對局部變量進行取址操作),編譯器就不得不將一些局部變量存放在棧中,這樣你也就能像全局變量一樣可以獲取到局部變量的地址了。

不過MDK還是很智能了,在這個例子中,watch 窗口 可以查看 temp 的值,但程序離開了這個函數,這個值必定是無法再查看了,不信可以試試。

以上就是魚鷹要分享的知識點,希望對各位道友有所幫助,下期再見。


1.做備忘|GD32 Arm MCU物聯網開發者線上課程不容錯過!

2.學嵌入式該不該參加培訓?

3.蘋果M1預示着RISC-V的崛起?

4.關於RISC-V啓動部分的思考~

5.你可能不瞭解的ARM處理異常之道!

6.有人說,這幾門語言要被淘汰了!

免責聲明:本文系網絡轉載,版權歸原作者所有。如涉及作品版權問題,請與我們聯繫,我們將根據您提供的版權證明材料確認版權並支付稿酬或者刪除內容。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章