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

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

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

C程序中常見的與內(nèi)存相關的錯誤及其解決辦法

STM32嵌入式開發(fā) ? 來源:STM32嵌入式開發(fā) ? 2023-06-14 17:13 ? 次閱讀

C語言入門程序員來說,管理和使用虛擬存儲器可能是個困難的,容易出錯的任務。與存儲器有關的錯誤屬于那些最令人驚恐的錯誤,因為它們經(jīng)常在時間和空間上,都在距錯誤源一段距離之后,才表現(xiàn)出來。

將錯誤的數(shù)據(jù)編寫到錯誤的位置,你的程序可能在最終失敗之前運行了好幾個小時,且使程序中止的位置距離錯誤的位置已經(jīng)很遠了。

1、間接引用壞指針

在進程的虛擬地址空間中有較大的漏洞,沒有映射到任何有意義的數(shù)據(jù)。如果我們試圖間接引用一個指向這些洞的指針,那么操作系統(tǒng)就會以段異常終止我們的程序。

而且,虛擬存儲器的某些區(qū)域是只讀的。試圖寫這些區(qū)域?qū)⒃斐梢员Wo異常終止這個程序。

間接引用壞指針的一個常見示例是經(jīng)典的scanf錯誤。假設我們想要使用scanf從stdin讀一個整數(shù)到變量。做這件事情正確的方法是傳遞給scanf一個格式串和變量的地址:

ea36476a-0a92-11ee-962d-dac502259ad0.png ????

然而,對于c語言程序員初學者而言,很容易傳遞val的內(nèi)容,而不是它的地址:

ea4a0b38-0a92-11ee-962d-dac502259ad0.png ????

在這種情況下,scanf將把val的內(nèi)容解釋為一個地址,并試圖將一個字寫到這個位置。在最好的情況下,程序立即以異常終止。

在最糟糕的情況下,val的內(nèi)容對應于虛擬存儲器的某個合法的讀/寫區(qū)域,于是我們就覆蓋了存儲器,這通常會在相當以后造成災難性的、令人困惑的后果。

2、讀未初始化的存儲器

雖然.bss存儲器位置(諸如未初始化的全局C變量)總是被加載器初始化為零,但是對于堆存儲器卻并不是這樣的。一個常見的錯誤就是假設堆存儲器被初始化為零:

ea61e03c-0a92-11ee-962d-dac502259ad0.png ????

在這個示例中,程序員不正確地假設向量y被初始化為零。正確的實現(xiàn)方式是在for循環(huán)時將y[i]設置為零,或使用calloc。

3、允許棧緩沖區(qū)溢出

如果一個程序不檢查輸入串的大小就寫入棧中的目標換成區(qū),那么這個程序就會有緩沖區(qū)溢出錯誤。例如,下面的函數(shù)就有緩沖區(qū)錯誤,因為gets函數(shù)拷貝一個任意長度的串到緩沖區(qū)。為了糾正這個錯誤,我們必須使用fgets函數(shù),這個函數(shù)限制了輸入串的大?。?br />
ea77efda-0a92-11ee-962d-dac502259ad0.png

4、假設指針和它們指向的對象是相同大小的

一種常見的錯誤是假設指向?qū)ο蟮闹羔樅退鼈兯赶虻膶ο笫窍嗤笮〉模?br />
ea8547ca-0a92-11ee-962d-dac502259ad0.png ????

這里的目的是創(chuàng)建一個由n個指針組成的數(shù)組,每個指針都指向一個包含m個int的數(shù)組。然而,因為程序員將int **A = (int **)malloc(n * sizeof(int));中將sizeof(int)寫成了sizeof(int),代碼實際創(chuàng)建的是一個int的數(shù)組。這段代碼只有在int和指向int的指針大小相同的機器上運行良好。

但是,如果我們在像Alpha這樣的機器上運行這段代碼,其中指針大于int,那么在for(i = 0; i < n; i++)? A[i] = (int *)malloc(m * sizeof(int));將寫到超過A數(shù)組末端的地方。因為這些字中的一個很可能是分配塊的邊界標記腳部,所以我們可能不會發(fā)現(xiàn)這個錯誤,而沒有任何明顯的原因。

5、造成錯位錯位

錯位錯誤是另一種很常見的覆蓋錯誤發(fā)生的原因:

ea991b7e-0a92-11ee-962d-dac502259ad0.png ????

這是前面程序的另一個版本。這里我們創(chuàng)建了一個n個元素的指針數(shù)組,但是隨后試圖初始化這個數(shù)組的n+1個元素,在這個過程中覆蓋了A數(shù)組后面的某個存儲器。

6、引用指針,而不是它所指向的對象

如果我們不太注意C操作符的優(yōu)先級和結(jié)合性,我們就會錯誤地操作指針,而不是期望操作指針所指向的對象。比如,考慮下面的函數(shù),其目的是刪除一個有*size項的二叉堆里的第一項,然后對剩下的*size-1項重新建堆。

eaa59a70-0a92-11ee-962d-dac502259ad0.png ???

*size—目的是減少size指針指向的整數(shù)的值。然而,因為一元—和*運算符優(yōu)先級相同,從右向左結(jié)合,所以代碼實際減少的是指針自己的值,而不是它所指向的整數(shù)的值。

如果幸運的話,程序會立即失敗,但是更有可能發(fā)生的是,當程序在它執(zhí)行過程的很后面產(chǎn)生一個不正確的結(jié)果時,我們只能在那里抓腦袋了。這里的原則是如果你對優(yōu)先級和結(jié)合性有疑問,就使用括號。使用表達式(*size)--。

7、誤解指針運算

另一種常見的錯誤是忘記了指針的算術(shù)操作是以它們指向的對象的大小為單位來進行的,而這種大小單位并不一定是字節(jié)。例如,下面函數(shù)的目的是掃描一個int的數(shù)組,并返回一個指針,指向val的首次出現(xiàn):

eaadef90-0a92-11ee-962d-dac502259ad0.png

8、引用不存在的變量

沒有太多經(jīng)驗的C程序員不理解棧的規(guī)則,有時會引用不再合法的本地變量,如下列所示:

eac44b8c-0a92-11ee-962d-dac502259ad0.png ????

這個函數(shù)返回一個指針,指向棧里的一個局部變量,然后彈出它的棧幀。盡管p仍然指向一個合法的存儲器地址,但是它已經(jīng)不再指向一個合法的變量了。

當以后在程序中調(diào)用其他函數(shù)時,存儲器將重用它們的幀棧。后來,如果程序分配某個值給*p,那么它可能實際正在修改另一個函數(shù)的幀棧中的一個條目,從而帶來潛在地災難性的、令人困惑的后果。

9、引用空閑堆塊中的數(shù)據(jù)

一個相似的錯誤是引用已被釋放了的堆塊中的數(shù)據(jù)。如下面的示例,示例中分配了一個整數(shù)數(shù)組x,之后釋放了塊x,最后又引用了它。

ead02362-0a92-11ee-962d-dac502259ad0.png

10、引起存儲器泄漏

存儲器泄漏是緩慢、隱形的殺手,當程序員不小心忘記釋放已分配塊,而在堆里創(chuàng)建了垃圾時,會發(fā)生這種問題。例如,下面的函數(shù)分配了一個堆塊x,然后不釋放它就返回。

eae5f37c-0a92-11ee-962d-dac502259ad0.png ????

如果leak經(jīng)常被調(diào)用,堆里就會充滿了垃圾,最糟糕的情況下,會占有整個虛擬地址空間。對于像守護進程和服務器這樣的程序來說,存儲器泄漏是特別嚴重的,根據(jù)定義這些程序是不會終止的。




審核編輯:劉清

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

    關注

    38

    文章

    7403

    瀏覽量

    163394
  • C語言
    +關注

    關注

    180

    文章

    7581

    瀏覽量

    135579
  • 虛擬機
    +關注

    關注

    1

    文章

    897

    瀏覽量

    27964

原文標題:C程序中常見的與內(nèi)存相關的錯誤

文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發(fā)】歡迎添加關注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關推薦

    C程序中常見的與內(nèi)存相關錯誤

    C語言入門程序員來說,管理和使用虛擬存儲器可能是個困難的,容易出錯的任務。與存儲器有關的錯誤屬于那些最令人驚恐的錯誤,因為它們經(jīng)常在時間和空間上,都在距
    發(fā)表于 06-14 17:13 ?333次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>程序</b><b class='flag-5'>中常見</b>的與<b class='flag-5'>內(nèi)存</b><b class='flag-5'>相關</b>的<b class='flag-5'>錯誤</b>

    C程序中10個與內(nèi)存有關的常見錯誤

    內(nèi)存有關的錯誤,屬于那種最令人驚恐的錯誤。在時間和空間上,經(jīng)常在距離錯誤源一段距離之后才表現(xiàn)出來。將錯誤的數(shù)據(jù)寫到
    發(fā)表于 06-20 10:41 ?655次閱讀

    EXE文件錯誤原因

      explorer.exe出現(xiàn)錯誤解決辦法應用程序錯誤,內(nèi)存不能為....的解決方法   運行某些
    發(fā)表于 08-25 15:14 ?0次下載

    聲卡硬件維修的常見問題及解決辦法

    聲卡硬件維修的常見問題及解決辦法 常見故障一:聲卡無聲   出現(xiàn)這種故障常見的原因有:
    發(fā)表于 02-23 14:25 ?2489次閱讀

    垂直熱風整平中常見問題解決辦法

    垂直熱風整平中常見問題解決辦法   熱風整平又叫噴錫,它的工作原理是利用熱風將印制板表面及孔內(nèi)多余焊料去掉,剩余焊料均
    發(fā)表于 03-02 09:35 ?773次閱讀

    開發(fā)中常遇電磁兼容EMC問題及解決辦法

    開發(fā)中常遇電磁兼容EMC問題及解決辦法 下面產(chǎn)品開發(fā)中常見的一些EMC問題: 一
    發(fā)表于 04-17 11:32 ?726次閱讀

    物理內(nèi)存使用率高的原因及解決辦法

    主要講解的就是物理內(nèi)存使用率高的原因以及他的解決辦法。導致物理內(nèi)存使用率高有幾種可能,而最常見的則有兩種:一是安裝不好的程序
    發(fā)表于 05-03 17:14 ?9319次閱讀
    物理<b class='flag-5'>內(nèi)存</b>使用率高的原因及<b class='flag-5'>解決辦法</b>

    Absinthe2.0越獄iOS5.1.1常見錯誤解決辦法

    Absinthe2.0越獄中可能會遇到一些問題,本內(nèi)容介紹了Absinthe2.0越獄iOS5.1.1常見錯誤解決辦法
    發(fā)表于 09-12 15:03 ?4635次閱讀

    Matlab編程常見錯誤解決辦法

    Matlab編程常見錯誤解決辦法求人不如求己
    發(fā)表于 03-16 15:58 ?0次下載

    一文知道Zynq平臺運行SDK程序錯誤解決辦法

    Zynq平臺運行SDK程序錯誤解決辦法,具體的跟隨小編一起來了解一下。
    的頭像 發(fā)表于 07-14 06:05 ?7954次閱讀

    KEIL C編譯器中常見的警告與錯誤信息的詳細解決辦法資料概述

    本文檔的主要內(nèi)容詳細介紹的是KEIL C編譯器中常見的警告與錯誤信息的詳細解決辦法資料概述。
    發(fā)表于 11-07 17:43 ?14次下載

    內(nèi)存條兼容異常問題的原因及其解決辦法

    經(jīng)常使用電腦的朋友都知道,電腦如果出現(xiàn)滴滴聲的 電腦開機 故障就是內(nèi)存條出現(xiàn)了問題。但是如果類似迅雷等軟件突然出現(xiàn)問題時,大多數(shù)朋友可能就不會想到是由于內(nèi)存出現(xiàn)了兼容性的問題了。下面,我就向大家介紹一下內(nèi)存條兼容異常問題的原因
    發(fā)表于 06-14 10:53 ?1.1w次閱讀

    C語言常見內(nèi)存錯誤及解決方法

      本文將帶您了解一些良好的和內(nèi)存相關的編碼實踐,以將內(nèi)存錯誤保持在控制范圍內(nèi)。內(nèi)存錯誤
    的頭像 發(fā)表于 02-14 13:10 ?3189次閱讀

    java內(nèi)存溢出的幾種原因和解決辦法

    內(nèi)存,但是如果程序中存在內(nèi)存泄漏(Memory Leak)或者使用不當?shù)臄?shù)據(jù)結(jié)構(gòu)等問題,仍然有可能導致內(nèi)存溢出。下面將詳細介紹Java內(nèi)存
    的頭像 發(fā)表于 11-23 14:44 ?5633次閱讀

    codeblocks環(huán)境錯誤解決辦法

    CodeBlocks是一款常用的集成開發(fā)環(huán)境,用于編寫、編譯和調(diào)試CC++等程序。然而,有時在使用CodeBlocks時可能會遇到一些錯誤或問題。本文將為你提供一些
    的頭像 發(fā)表于 11-26 09:37 ?5528次閱讀