0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

數(shù)組越界的問題解析

魚鷹談單片機 ? 來源:魚鷹談單片機 ? 2023-04-17 09:15 ? 次閱讀

數(shù)組越界問題大家在軟件開發(fā)過程中應該都司空見慣了。如果你沒見過,大概率是一個新手,工作經驗不足,倒不是說你自己會生產這種 BUG,但有些同事卻可能是 BUG 搬運工。

在魚鷹五年的工作開發(fā)過程中,除了在北京剛畢業(yè)那會沒遇到這種隱藏問題(碰到的都是自己生產的 BUG,不過自產自銷,也還行),在深圳的這幾家公司都遇到了數(shù)組越界的問題。

問題一

第一個問題是關于串口驅動導致的越界(最終結果是 hardfault),這個魚鷹在以前的筆記中也反復強調了,因為這個問題差點導致自己熬了一個通宵,也是醉了(老代碼的一個 bug)。

當然這個問題的解決和當時沒有在線調試環(huán)境(當時的 PCB 板子通過串口燒錄代碼,沒有調試接口,大坑)有很大關系,否則解決起來會快不少。

當然當時魚鷹也沒掌握這個方法《BUG 終結者,現(xiàn)場抓獲!|顛覆認知》,否則出現(xiàn)問題時,這種小問題分分鐘定位它。

所以當時解決這個問題,全靠玄學:運氣。

否則這個問題不知道要蹂躪魚鷹多少天。

問題二

這個問題在前東家遇到。當時的環(huán)境是 boot + app 形式。boot 代碼也是跑了多年的老代碼,從來沒有出現(xiàn)過問題。

直到有一次版本升級,發(fā)現(xiàn)程序不能跳轉到 app 正常運行(具體細節(jié)不記得了)。

當時有同事懷疑是我當時更新的 printf 打印函數(shù)有關系,因為當時的版本更新有這個改動。但魚鷹對自己寫的代碼還是比較有自信的,并且我的 printf 改動和 app 跳轉能有什么關系。

但懷疑到你頭上了,同時魚鷹也經常負責定位這類疑難雜癥,剛好空閑,那就去瞧瞧看了,證明一下這不是你的問題。

因為問題 100% 復現(xiàn),又掌握了那個現(xiàn)場抓獲的技巧,很快就定位到是 boot 的一段代碼申請的棧數(shù)組空間不足,導致被調用的函數(shù)使用這塊空間時越界了。

類似下面這種:

func2(uint8_t*buff)
{
i=5;
buff[i]= 0;
}
fun1()
{
uint8_t buff[4];
func2(buff);
}

當然實際代碼肯定不可能這么簡單,i 的值是變化的,不可能一眼看出。

這個問題也是導致 hardfault(退出 func2 時,破壞了返回地址)。

看到沒有,有時候二分法(二分查找有問題的代碼提交)查找問題也不是那么可靠,因為問題可能根本不在提交的的代碼中。

而下面的問題三也證明了這一點(當然不是說二分法沒用,只是不能全靠它作為你的結果判斷)。

問題三

這個問題是現(xiàn)東家遇到的問題。

自己開發(fā)的一個新模塊,當合并到主分支時,發(fā)現(xiàn)開機必定 hardfault,這讓我百思不得其解。自己新加入的代碼,都沒用到數(shù)組,怎么會hardfault。

我的第一反應就是,不是我的鍋。

但問題出現(xiàn)在我合并的過程,也只能由我定位了。還好經驗豐富,一天時間+加班幾個小時,總算是定位到了。

這個問題定位有幾個難點:

1、使用 C++

2、使用O2 優(yōu)化,而使用 O0 的方式問題不復現(xiàn)了(最蛋疼)

3、使用了 map 庫函數(shù)

因此在復現(xiàn)率很高的情況下,還是花了這么多時間。

但好在順利解決了(這么高的復現(xiàn)率,定位root case只是時間問題,信心也是 100%)。

簡單來說,是以前的一段代碼在使用 sprintf 時(這里強烈建議用 snprintf),導致棧緩存空間越界,然后導致上一層函數(shù)的局部變量被篡改,而這個局部變量會導致 map 傳入的參數(shù)有問題,最終導致了 hardfault 。

可以看到,雖然根因在一個函數(shù)中,但最終出現(xiàn)問題卻可能在另一個函數(shù)中。

就像犯罪現(xiàn)場,作案現(xiàn)場只有一個(root case),但可能案發(fā)現(xiàn)場并不是作案現(xiàn)場。

因此解決 bug 過程其實就是警察破案,通過蛛絲馬跡找到第一作案現(xiàn)場,如此才能正確破案。

而這種代碼在工程里面有好幾處.....并且在合入我的代碼之前,運行良好。所以,數(shù)組越界也不一定會 hardfault,就看你破壞的是啥了。

為什么?

大家很奇怪,為毛數(shù)據越界大部分情況下會 hardfault,有時卻不會產生問題。只有思考到更深層的原因,你才能在 BUG 環(huán)繞中有所成長。

這個時候,就看你的基礎扎實不扎實了。

這里來個簡單示意函數(shù)(優(yōu)化O0)

void func2()
{
inti= 0;
intbuff[4];
 
 buff[4] = 0;
}
voidfunc1()
{
intj=0;//假設該局部變量使用r4
func2();
}

棧空間如下(因為只有 4 個字,編譯器可能 buff[4] 直接使用寄存器了,但為了簡單說明,這里假設 buff 都使用了棧):

552128a6-dcbc-11ed-bfe3-dac502259ad0.png

從上圖我們可以知道,進入 func2 函數(shù)時,先 push,離開時 pop。

局部變量 i 使用 r4 寄存器,但是??臻g r4 保存的是 func1 使用的j的值。

因此,當我們數(shù)組越界時(一般越界是往高地址,因為數(shù)組索引一般是自加),很容易破壞上一個函數(shù)的??臻g,在這里破壞的是 j 的值。如果 j 很重要,那么很可能會導致 hardfault 或者其它問題(能引起 hardfault 反而是好事)。

并且這里面還有重要的返回地址 lr,如果這個值被越界破壞,那么大概率都是hardfault,因為你企圖跳轉到一個不存在的地址執(zhí)行。

數(shù)組越界是一個很危險的 BUG,能觀察到現(xiàn)象還好,萬一是默默破壞而不能很快被察覺,成為一個隱藏 BUG,那才是最危險的。

那為啥問題三增加別的代碼會觸發(fā)這個 BUG ,修改優(yōu)化等級又會消失呢?

這和編譯器有關系,有可能你的代碼導致有問題的代碼使用了不同的內存布局,從而越界篡改的位置變成了重要的內存,因此出現(xiàn)了現(xiàn)象,而優(yōu)化等級對棧內存布局更是有很大影響。

另外本篇筆記介紹的局部緩存數(shù)組的越界,實際上還有全局數(shù)組的越界,那種問題相對簡單許多,看 map 文件即可。

因此,操作數(shù)組時,一定要時時刻刻檢測數(shù)組的索引的大小,以防越界。





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關注

    關注

    31

    文章

    5268

    瀏覽量

    119646
  • C++語言
    +關注

    關注

    0

    文章

    147

    瀏覽量

    6944
  • 數(shù)組越界

    關注

    0

    文章

    2

    瀏覽量

    5518
  • printf函數(shù)

    關注

    0

    文章

    31

    瀏覽量

    5870

原文標題:數(shù)組越界是一顆隱形炸彈

文章出處:【微信號:emOsprey,微信公眾號:魚鷹談單片機】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    越界智能監(jiān)測攝像機

    隨著科技的不斷發(fā)展,越界智能監(jiān)測攝像機在安防領域得到了廣泛應用。這種智能監(jiān)測設備結合了圖像識別技術和人工智能算法,旨在實現(xiàn)對區(qū)域內物體的越界行為進行監(jiān)測和警示。通過高清晰度的攝像頭捕捉到場景中的物體
    的頭像 發(fā)表于 09-05 11:06 ?151次閱讀
    <b class='flag-5'>越界</b>智能監(jiān)測攝像機

    labview字符串數(shù)組轉化為數(shù)值數(shù)組

    在LabVIEW中,將字符串數(shù)組轉換為數(shù)值數(shù)組是一項常見的任務,尤其是在處理數(shù)據采集、信號處理或用戶輸入時。 1. 理解LabVIEW的數(shù)據類型 在開始之前,了解LabVIEW中的數(shù)據類型是非
    的頭像 發(fā)表于 09-04 17:47 ?1002次閱讀

    深入探索KUKA KRL中的數(shù)組應用

    如果 CHAR 類型數(shù)組的所有數(shù)組元素都擁有相同的字符串,則不必單獨初始化每個數(shù)組元素。忽略右側的數(shù)組下標。(對于一維數(shù)組下標,不寫下標。)
    的頭像 發(fā)表于 04-18 10:37 ?1021次閱讀
    深入探索KUKA KRL中的<b class='flag-5'>數(shù)組</b>應用

    數(shù)組和鏈表在內存中的區(qū)別 數(shù)組和鏈表的優(yōu)缺點

    數(shù)組和鏈表在內存中的區(qū)別 數(shù)組和鏈表的優(yōu)缺點? 數(shù)組和鏈表是常見的數(shù)據結構,用于組織和存儲數(shù)據。它們在內存中的存儲方式以及優(yōu)缺點方面存在一些顯著的差異。本文將詳細探討這些差異以及它們的優(yōu)缺點。 1.
    的頭像 發(fā)表于 02-21 11:30 ?759次閱讀

    PHP中數(shù)組的使用方法!

    PHP中數(shù)組的使用方法! PHP是一種廣泛使用的網絡編程語言,它的數(shù)組功能非常強大且靈活。數(shù)組是一種數(shù)據結構,它允許我們在單個變量中存儲多個值。 在本篇文章中,我將詳細解釋PHP數(shù)組
    的頭像 發(fā)表于 01-12 15:11 ?456次閱讀

    光耦失效的幾種常見問題解析

    光耦失效的幾種常見問題解析? 光耦失效是一個常見的問題,特別是在電子設備中經常使用光耦進行隔離和信號傳輸?shù)那闆r下。下面將詳細介紹一些光耦失效的常見問題以及解析。 1. 輸出信號弱或無輸出 有時,光耦
    的頭像 發(fā)表于 12-25 14:30 ?5421次閱讀

    數(shù)組和指針不相同嗎?數(shù)組和指針有哪些區(qū)別

    數(shù)組就是指針,指針就是數(shù)組,這樣的言論在評論區(qū)看到不下于10次。
    的頭像 發(fā)表于 12-13 16:34 ?1150次閱讀
    <b class='flag-5'>數(shù)組</b>和指針不相同嗎?<b class='flag-5'>數(shù)組</b>和指針有哪些區(qū)別

    數(shù)組與指針不能混用的情況

    數(shù)組與指針不能混用的情況? 數(shù)組與指針是 C/C++ 中非常常見的特性和概念。然而,在某些情況下,數(shù)組與指針是不能混用的。這種情況通常涉及到數(shù)組的內存分配和
    的頭像 發(fā)表于 12-07 13:46 ?528次閱讀

    C語言中數(shù)組的用法

    C語言的數(shù)組是一種數(shù)據結構,它可以存儲多個相同類型的數(shù)據,例如整數(shù),字符,浮點數(shù)等。數(shù)組的每個元素都有一個索引,用來表示它在數(shù)組中的位置。數(shù)組的索引從0開始,也就是說,
    的頭像 發(fā)表于 11-24 17:48 ?1144次閱讀
    C語言中<b class='flag-5'>數(shù)組</b>的用法

    c語言中數(shù)組怎么定義

    C語言中,數(shù)組是一種用來存儲相同類型元素的數(shù)據結構。它可以存儲多個元素,并通過一個共同的名稱來引用這些元素。數(shù)組是一種很重要的數(shù)據結構,可以用于解決很多實際的問題。 在C語言中,定義數(shù)組的語法如下
    的頭像 發(fā)表于 11-24 10:11 ?2556次閱讀

    C語言如何創(chuàng)建數(shù)組

    C語言是一種非常強大和靈活的編程語言,它提供了若干數(shù)據類型來存儲和操作數(shù)據。其中之一就是數(shù)組,它可以用來存儲一系列具有相同數(shù)據類型的元素。本文將詳細介紹如何在C語言中創(chuàng)建數(shù)組,并探討數(shù)組的一些常見
    的頭像 發(fā)表于 11-24 10:08 ?1521次閱讀

    C語言求數(shù)組長度的5種方法

    [0]);printf("Arraylength:%d\n",length);return0;}解析:sizeof(array)返回整個數(shù)組的字節(jié)大小,sizeo
    的頭像 發(fā)表于 11-19 08:00 ?2510次閱讀
    C語言求<b class='flag-5'>數(shù)組</b>長度的5種方法

    Linux程序內存越界定位分析

    。經分析發(fā)現(xiàn)是庫源代碼里一全局數(shù)組內存地址大面積越界到其他全局數(shù)組了。 問題現(xiàn)象:現(xiàn)象為觸發(fā)某個業(yè)務條件,將導致程序邏輯運行不正常,異常log如下圖,可看出“g_s32MaxFd”變量的值(文件句柄)被置0,正常情況應該是大于0
    的頭像 發(fā)表于 11-13 11:30 ?393次閱讀
    Linux程序內存<b class='flag-5'>越界</b>定位分析

    什么是數(shù)組?數(shù)組有什么用?數(shù)組的使用方法

    數(shù)組(Array)是有序的元素序列。
    的頭像 發(fā)表于 11-08 14:58 ?1464次閱讀
    什么是<b class='flag-5'>數(shù)組</b>?<b class='flag-5'>數(shù)組</b>有什么用?<b class='flag-5'>數(shù)組</b>的使用方法

    燃爆!煤礦安全,人員越界識別的必要性!

    人員越界識別AI算法作為智慧礦山AI算法的一大創(chuàng)新,應用于煤礦安全管理中,通過實時監(jiān)測和預警,有效避免人員越界引發(fā)的事故,提升煤礦的安全性和生產效率。
    的頭像 發(fā)表于 10-30 15:03 ?312次閱讀