精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

關于C程序中10個與內存有關的常見錯誤

Dp1040 ? 來源:一起學嵌入式 ? 2023-06-20 10:41 ? 次閱讀

與內存有關的錯誤,屬于那種最令人驚恐的錯誤。在時間和空間上,經常在距離錯誤源一段距離之后才表現出來。將錯誤的數據寫到錯誤的位置,你的程序可能在最終失敗之前運行了一段時間。

下面列舉并分析了與內存有關的幾種錯誤:

1、間接引用壞指針

如果間接引用一個指向沒有任何意義的數據的指針,那么操作系統會以段異常終止程序。如果向只讀區域中寫入數據,這些區域會以保護異常終止這個程序。

一個常見的經典示例是scanf錯誤。這個函數用處是從標準輸入讀入一個整數到一個變量,正確的寫法是傳遞給scanf一個格式串和變量的地址:

scanf("%d", &value);

然而,常見的書寫錯誤如下:

scanf("%d", value);

這種情況下,scanf將把value內容解釋為一個地址,并試圖將一個字寫到這個位置。這會導致程序出現異常,有時會立即終止;有時會在相當長的時間后造成災難性、令人困惑的后果。

2、讀未初始化的內存

常見的錯誤是假設堆內存被初始化為零:

int *matvec(int **A, int *x, int n)
{
int i, j;
int *y = (int *)malloc(n * sizeof(int));

for(i = 0; i < n; i++)
????{
????????for(j = 0; j < n; j++)
????????{
????????????y[i] += A[i][j] * x[j]
????????}
????}
????return y;
}
示例中不應該假設新申請的內存地址(y指向的地址)被初始化為零;正確的做法是顯式地將y[i]設置為零,或者使用calloc申請內存。

3、棧緩沖區溢出

如果一個程序不檢查輸入字符串的大小就寫入棧中目標緩沖區,那么這個程序就會出現緩沖區溢出的錯誤,如下程序:

void buff()
{
char buf[64];

gets(buf);
return;
}
這個函數會出現緩沖區溢出錯誤,因為gets函數只是簡單復制一個任意長度的字符串到緩沖區,不限制輸入串的大小。解決這個問題的方法是,可以用限制了輸入串大小的fgets函數。

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

常見的錯誤是,假設指向對象的指針和它們所指向的對象是相同大小的,示例程序:

int **makeArray(int n, int m)
{
int i;
int **A = (int **)malloc(n * sizeof(int)); /* 注意此處語句,存在問題 */

for(i = 0; i < n; i++)
????{
????????A[j] = (int *)malloc(m * sizeof(int));
????}
????return A;
}
此程序的目的是創建一個由n個指針組成的數組,每個指針都指向一個包含m個int的數組。然而,第4行程序代碼將sizeof(int *)寫成了sizeof(int),代碼實際上創建的是一個int的數組。

這段代碼只有在int和指向int的指針大小相同的機器上運行良好,否則就會出現錯誤。

5、內存越界

這種錯誤會越界覆蓋原有內存的數據,導致出錯:

int **makeArray(int n, int m)
{
int i;
int **A = (int **)malloc(n * sizeof(int)); /* 注意此處語句,存在問題 */

for(i = 0; i <= n; i++) /* 注意循環終止條件 */
????{
????????A[j] = (int *)malloc(m * sizeof(int));
????}
????return A;
}
程序在第6行和第8行試圖初始化這個數組的n+1個元素,這個過程會覆蓋A數組后面的某個內存位置。

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

如果不太注意C操作符的優先級和結合性,我們就會錯誤地操作指針,而不是指針所指向的對象。如果想要減少某個指針指向的整數的值,代碼書寫如下:

*ptr--;

然而,因為一元運算符“--”和“*”的優先級相同,且從右向左結合。那么上述代碼實際的效果為*(ptr--),即減少的是指針自己的值,而不是它所指向的整數的值。

如果對優先級和結合性有疑問的時候,就用括號。修正后的代碼如下:

(*ptr)--;

7、誤解指針運算

這類錯誤是忘記指針的算術運算操作是如何進行,是以指針指向的對象的大小為單位進行的,而這種大小單位并不一定是字節。 例如,掃描一個int的數組,并返回一個指向val首次出現的指針:

int *search(int *p, int val)
{
while(*p && *p != val)
{
p += sizeof(int);
}
return p;
}
每次循環時,第5行都把指針加了4(一個整數的字節數),函數就不正確地掃描了數組中每4個整數。

8、引用不存在的變量

有的C程序員不太理解棧的規則,有時會引用不再合法的局部變量,如下所示:

int *stackref()
{
int val;

return &val;
}

這個函數返回一個指針(假設為ptr),指向棧里的一個局部變量,然后彈出它的棧幀。盡管ptr仍然指向一個合法的內存地址,但它已經不再指向一個合法的變量了。

以后在程序中調用其他函數時,內存將重用它們的棧幀。如果程序賦值給*ptr,那么它可能實際上正在修改另一個含的棧幀中的數據,從而潛在地帶來災難性的后果。

9、引用空閑堆塊中的數據

引用已經被釋放了的堆塊中的數據會導致出錯。例如:

int *heapref(int n, int m)
{
int i;
int *x, *y;

x = (int *)malloc(n * sizeof(int)); /* 申請內存 */

...

free(x); /* 釋放內存 */

y = (int *)malloc(m * sizeof(int));
for(i = 0; i < m; i++)
????{
????????y[i] = x[i]++;
????}

????return y;
}

當程序在第15行引用x[i]時,數組x可能已經是某個其他已分配堆塊的一部分了,其內容也許被重寫了。導致程序運行結果與預期不符合,出現錯誤。

10、引起內存泄漏

內存泄漏是緩慢、隱形的殺手,當程序員不小心忘記釋放已分配的內存塊,而在堆里創建了垃圾時,會發生這種問題。如下:

void leak(int n)
{
int *x = (int *)malloc(n * sizeof(int));

return;
}
如果經常調用這個函數,漸漸地堆里會充滿了垃圾,造成內存泄漏。另外,有時也會引起程序終止或其他問題。

小結

以上總結了C程序中,管理和使用內存常見的錯誤類型,并舉例進行了說明。在實際的編程中,應該避免出現這些錯誤,否則會出現意想不到的后果。





審核編輯:劉清

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

    關注

    180

    文章

    7598

    瀏覽量

    136198
收藏 人收藏

    評論

    相關推薦

    CC++語言開發內存直接操作的方法

    指針釋放引起的錯誤:釋放同一內存塊兩次,或釋放一塊未曾使用malloc分配的內存,或釋放仍在使用
    的頭像 發表于 05-09 10:56 ?9013次閱讀
    在<b class='flag-5'>C</b>和<b class='flag-5'>C</b>++語言開發<b class='flag-5'>中</b><b class='flag-5'>內存</b>直接操作的方法

    FPGA設計中經常犯的10錯誤

    本文列出了FPGA設計中常見的十錯誤。我們收集了 FPGA 工程師在其設計犯的 10
    發表于 05-31 15:57 ?1080次閱讀
    FPGA設計中經常犯的<b class='flag-5'>10</b><b class='flag-5'>個</b><b class='flag-5'>錯誤</b>

    C程序常見的與內存相關的錯誤

    C語言入門程序員來說,管理和使用虛擬存儲器可能是困難的,容易出錯的任務。與存儲器有關錯誤屬于那些最令人驚恐的
    發表于 06-14 17:13 ?346次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>程序</b>中<b class='flag-5'>常見</b>的與<b class='flag-5'>內存</b>相關的<b class='flag-5'>錯誤</b>

    C程序10內存有關常見錯誤

    內存有關錯誤,屬于那種最令人驚恐的錯誤。在時間和空間上,經常在距離錯誤源一段距離之后才表現出來。將錯誤的數據寫到
    發表于 06-20 10:41 ?670次閱讀

    【原創】常見內存錯誤及對策

    校驗也起不了作用,沒有被 初始化的指針變量,內部是一非NULL的亂碼assert是一宏,而不是函數,包含在assert.h頭文件。如果其后面括號里的值為假,則程序終 止運行,并提
    發表于 08-24 11:34

    動態內存錯誤的靜態檢測

    內存泄漏、空指針引用等動態內存錯誤在/,/LL等支持動態內存操作的程序普遍存在在
    發表于 06-10 16:29 ?52次下載
    動態<b class='flag-5'>內存</b><b class='flag-5'>錯誤</b>的靜態檢測

    糾正10有關編程的常見誤區

    在編程行業,一直流傳著很多誤區。下面讓我們一起來糾正10有關編程的常見誤區,以幫助編程初學者或有志成為程序員的人,更理性地認識編程。
    的頭像 發表于 02-02 16:02 ?3334次閱讀

    關于NAND閃存有哪些觀念是錯誤的?

    在半導體業,有非常多與接口標準、性能規格、功能特性和設計的真實可能性有關聯的假設、術語和誤解。因此,弄清事實很重要。本文將闡明關于NAND閃存的錯誤觀念。
    發表于 08-30 14:39 ?943次閱讀

    虛擬內存有什么用

    虛擬內存有什么用?雖說內存的大小會直接影響我們電腦的運行的程序個數和運行速度,但是當內存的容量剩余很少的時候,再運行電腦程序的時候,電腦就會
    的頭像 發表于 03-14 14:55 ?1.4w次閱讀

    關于PCBA設計10常見錯誤介紹

    排名前10位的PCBA錯誤設計要避免 ,這里列出了10常見錯誤,以及如何輕松避免這些
    的頭像 發表于 02-27 10:20 ?2279次閱讀

    C語言常見內存錯誤及解決方法

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

    關于C語言的10技巧

    硬件工程師最常見的工作內容是通過寫代碼來測試硬件。這10C語言技巧(C語言仍然是常見的選擇)可
    發表于 10-18 09:10 ?685次閱讀

    C程序常見的與內存相關的錯誤及其解決辦法

    C語言入門程序員來說,管理和使用虛擬存儲器可能是困難的,容易出錯的任務。
    的頭像 發表于 06-14 17:13 ?1010次閱讀
    <b class='flag-5'>C</b><b class='flag-5'>程序</b>中<b class='flag-5'>常見</b>的與<b class='flag-5'>內存</b>相關的<b class='flag-5'>錯誤</b>及其解決辦法

    常用的解決內存錯誤的方法

    1. 內存管理功能問題 由于C++語言對內存有主動控制權,內存使用靈活和效率高,但代價是不小心使用就會導致以下內存
    的頭像 發表于 11-10 15:29 ?1453次閱讀
    常用的解決<b class='flag-5'>內存</b><b class='flag-5'>錯誤</b>的方法

    ug內部錯誤,內存訪問違例怎么解決

    ug內部錯誤,內存訪問違例怎么解決 內部錯誤內存訪問違例是編程中常見的問題,它們可能會導致應用程序
    的頭像 發表于 12-27 16:27 ?6074次閱讀