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

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

3天內(nèi)不再提示

程序中增加一個變量導致異常的分析

typedef ? 來源:typedef ? 2024-01-22 09:56 ? 次閱讀

前述

大家在平常的編程過程應該會碰到各種奇葩的問題吧,反正我最近是碰到了一次,再此跟大家分享一下。事情的原因是我在程序中增加了一個變量,然后就會導致程序每次都會進入異常。

示例代碼

我將代碼簡化了,使用兩個模塊來演示這個問題。第一個模塊是Dev模塊。

下面是Dev模塊的頭文件,Dev結構體中有一個數(shù)組。

#include
#include

typedefstruct{
inta_[100];
charb_;
}Dev;

voidDevInit(Dev*c_this);

下面是Dev模塊的源文件代碼,里面只有一個memset。

#include"Dev.h"

voidDevInit(Dev*c_this){
memset(c_this,0,sizeof(Dev));
}

第二個模塊是DevManager,相關數(shù)據(jù)結構如下:

#include"Dev.h"

#pragmapack(1)

typedefstruct{
Devuart_;
charnum_;//Addingthisvariablecausesacrash
Deviic_;
}DevManage;

#pragmapack()

DevManagedev_manage;

voidDevManagerInit(void){
DevManage*c_this=&dev_manage;

memset(c_this,0,sizeof(DevManage));

DevInit(&c_this->uart_);
DevInit(&c_this->iic_);
}

DevManage結構體包含uart以及iic設備,以及我新加入的一個num_變量,由于新增了num_變量以及與之相關的業(yè)務會導致每次調(diào)試目標板都會進入異常。

嘗試解決異常問題

根據(jù)調(diào)試情況看,每次都會出現(xiàn)異常,說明是個小問題。就怕偶爾出現(xiàn)異常,不容易復現(xiàn)。

思路應該非常清晰,出現(xiàn)異常時候查看LR寄存器的值,LR寄存器主要有兩個功能。

保存子程序返回地址。使用BL或BLX時,跳轉指令自動把返回地址放入r14中

當異常發(fā)生時,異常模式的R14用來保存異常返回地址

根據(jù)LR寄存器的值,從而定位到是執(zhí)行DevInit(&c_this->iic_)函數(shù)中的memset導致的。

第一反應是DevInit中傳入的對象可能為空,操作了非法內(nèi)存才導致的錯誤。于是又重新調(diào)試了一遍,發(fā)現(xiàn)DevInit中對象的地址并不為空,而且就是等于實體對象中設備的地址。

這一刻我陷入了深深的自我懷疑,memset難道不是這樣用的?難道不是傳入一個地址,清0,然后sizeof(DevManage)就完事了?

我這代碼怎么會出錯,memset就是這樣用的,天王老子來我也是對的,這樣的心理是不是也深度還原了碰到問題時的你們。

如果是你,該如何繼續(xù)...

救命稻草

有人說,匯編是最后的救命稻草。那我也嘗試抓住這根稻草,出現(xiàn)問題時如下圖:

1b2d08ce-b8c4-11ee-8b88-92fbcf53809c.png

問題主要出現(xiàn)紅色箭頭指向的這一行,經(jīng)過查詢資料得知_aeabi_memclr4是一個用于ARM嵌入式系統(tǒng)的函數(shù),用于將內(nèi)存區(qū)域清零。函數(shù)名中的"_a"表示該函數(shù)符合ARM嵌入式應用二進制接口(Embedded Application Binary Interface,EABI)規(guī)范。在調(diào)用_aeabi_memclr4時,需要確保傳入的內(nèi)存地址是四字節(jié)對齊的。再看圖片中的對象地址為0x200001BD,剛好比四字節(jié)對齊地址0x200001BC多了一個字節(jié)。

再回頭看DevManage對象,這里使用了偽指令#pragma pack(1)讓內(nèi)存分配進行單字節(jié)對齊。因為Dev對象是按照四字節(jié)對齊的,緊接著引入了新的成員num_占用一個字節(jié)。所以導致iic_對象的地址相對于未增加變量之前的地址偏移了一個字節(jié),導致不是四字節(jié)對齊的了,從而引發(fā)了錯誤。

就示例中的代碼而言,只需要把強制DevManage對象單字節(jié)對齊的功能刪除即可解決問題,因為默認情況下是四字節(jié)對齊的。

成員分配

由于#pragma pack(1)具有作用域限制,這里其實只是對num_變量做了單字節(jié)對齊的限制,而并沒有對Dev對象的內(nèi)存分配起到限制作用,Dev對象仍然是按照4字節(jié)對齊的(默認值),所以Dev對象的所占用的長度一定是101*4=404字節(jié)。而整個DevManager對象的大小就101 * 4 + 1 + 101 * 4 = 809字節(jié),成員分配如下圖所示。

1b37ac7a-b8c4-11ee-8b88-92fbcf53809c.png

最后

到最后在拋出一個問題,對于上述的代碼在vscode中使用gcc編譯執(zhí)行為何沒有問題?

審核編輯:湯梓紅

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

    關注

    7

    文章

    2613

    瀏覽量

    47010
  • 編程
    +關注

    關注

    88

    文章

    3521

    瀏覽量

    93268
  • 程序
    +關注

    關注

    115

    文章

    3720

    瀏覽量

    80357
  • 變量
    +關注

    關注

    0

    文章

    607

    瀏覽量

    28257

原文標題:加個變量,程序崩了

文章出處:【微信號:typedef,微信公眾號:typedef】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    數(shù)據(jù)波形數(shù)據(jù)異常分析

    ,試驗過程,V1-的電壓出現(xiàn)了異常點3.95V(試驗進行了7、8小時后),如下圖所示,左側圖為持續(xù)監(jiān)控圖,右側圖為正常傳感器的監(jiān)控圖
    發(fā)表于 11-21 11:55

    分析關于STM32 芯片異常復位的經(jīng)典案例!

    應用軟件產(chǎn)生異常的地方!問題描述某STM32用戶反饋,當使用STM32L4芯片的時候,程序運行段時間后,會忽然復位。復位后程序繼續(xù)運行,但是還會繼續(xù)復位,原因不詳!問題
    發(fā)表于 04-07 08:00

    STM32局部變量過大導致棧溢出怎么去解決呢

    最近項目調(diào)試中發(fā)現(xiàn)只要使用memset函數(shù)對局部數(shù)組賦值時,就會導致其他全局變量值被更改,接著就進入HardFault錯誤。后來發(fā)現(xiàn)局部變量
    發(fā)表于 01-20 06:07

    Labview的異常崩潰

    起因:昨天升級程序后產(chǎn)線突然反饋程序異常崩潰,排查到了神奇的BUG。Labview異常崩潰報
    發(fā)表于 03-17 18:05

    請問main函數(shù)內(nèi)定義的變量是在棧上嗎?

    程序調(diào)試很久直數(shù)據(jù)異常,后來無意發(fā)現(xiàn)main函數(shù)內(nèi)定義的變量定義在main以外后程序功能正
    發(fā)表于 04-01 10:12

    XDATA定義變量程序異常的原因?怎么解決?

    本人第次使用新塘N76E003單片機開發(fā),在定義變量時DATA用完了以后,使用XDATA定義變量,發(fā)現(xiàn)用XDATA定義的變量程序運行時
    發(fā)表于 06-25 06:05

    實時任務處理程序設計“易變的”變量

    實時任務處理程序設計“易變的”變量
    發(fā)表于 05-15 13:52 ?7次下載

    變量水質(zhì)參數(shù)時間異常事件檢測算法

    在供水管網(wǎng)中部署傳感器網(wǎng)絡實時獲取多個水質(zhì)參數(shù)時間序列數(shù)據(jù),當供水管網(wǎng)發(fā)生污染時,高效準確地檢測水質(zhì)異常重要問題。提出多變量水質(zhì)參數(shù)時間異常
    發(fā)表于 12-07 16:17 ?0次下載
    多<b class='flag-5'>變量</b>水質(zhì)參數(shù)時間<b class='flag-5'>異常</b>事件檢測算法

    西門子PLC變量定義變量

    。 程序多數(shù)指令都通過變量來操作。? 為指令分配變量后,即會使用指定變量的值來執(zhí)行該指令。 變量
    的頭像 發(fā)表于 12-23 16:25 ?1.9w次閱讀
    西門子PLC<b class='flag-5'>變量</b>表<b class='flag-5'>中</b>定義<b class='flag-5'>變量</b>

    怎么給全局變量別名

    所謂的變量別名,就是通過通過不同的標識符,來表示同一個變量。我們知道,變量名稱是給程序員使用的。在編譯器的眼中,所有的
    的頭像 發(fā)表于 02-14 13:38 ?450次閱讀
    怎么給全局<b class='flag-5'>變量</b>起<b class='flag-5'>一</b><b class='flag-5'>個</b>別名

    Python異常機制(

    刻不在路上. 在今夜首先了解 什么是異常 : 軟件程序在運行過程,可能會遇到能使其不能正常運行的問題,我們稱之為異常,英文是:Excep
    的頭像 發(fā)表于 05-11 18:17 ?683次閱讀
    Python<b class='flag-5'>中</b>的<b class='flag-5'>異常</b>機制(<b class='flag-5'>一</b>)

    讀取機器人程序變量

    其中包含引用解釋器的進程指針的數(shù)據(jù). 變量包含接下來將在解釋器執(zhí)行的塊的數(shù)據(jù)。 根據(jù)特定的解釋器,訪問數(shù)據(jù)的方式如下: 讀取機器人程序變量
    的頭像 發(fā)表于 05-29 10:02 ?881次閱讀
    讀取機器人<b class='flag-5'>程序</b><b class='flag-5'>中</b>的<b class='flag-5'>變量</b>

    Java oom異常的原因分析

    據(jù),而棧內(nèi)存用于存儲方法調(diào)用和局部變量。 當程序需要使用更多內(nèi)存時,會向操作系統(tǒng)請求更多的內(nèi)存空間。如果操作系統(tǒng)無法分配足夠的內(nèi)存空間,就會導致OOM異常的發(fā)生。
    的頭像 發(fā)表于 12-05 13:43 ?627次閱讀

    C語言:指針內(nèi)存是如何存放變量

    程序定義變量,那么在程序編譯的過程,系統(tǒng)會
    發(fā)表于 01-08 10:14 ?355次閱讀

    變量位置不同會死機?郭天祥老師視頻的遺留問題分析答案

    在郭天祥老師視頻里有問題分享,是EXMC初始化里的變量定義和初始化位置不同會導致
    的頭像 發(fā)表于 02-26 09:12 ?266次閱讀
    <b class='flag-5'>變量</b>位置不同會死機?郭天祥老師視頻的遺留問題<b class='flag-5'>分析</b>答案