【C】 41_記憶體操作經典問題分析 一

TianSong發表於2019-05-14

野指標

  • 指標變數中的值是非法的記憶體地址,進而形成野指標
  • 野指標不是 NULL 指標,是指向不可用記憶體地址的指標
  • NULL 指標並無危害,很好判斷,也很好除錯
  • C 語言中無法判斷一個指標所儲存的地址是否合法

野指標的由來

  • 區域性指標變數沒有被初始化
  • 指標所指向的變數在指標之前被銷燬(返回區域性變數地址或陣列)
  • 使用已經釋放過的指標
  • 進行了錯誤的指標運算
  • 進行了錯誤的強制型別轉換

例項分析: 野指標初探

#include <stdio.h>
#include <malloc.h>

int main()
{
    int* p1 = (int*)malloc(40);
    int* p2 = (int*)1234567;    // 進行強制的錯誤型別轉換,造成野指標
    int i = 0;
    
    for(i=0; i<40; i++)
    {
        *(p1 + i) = 40 - i;    // 記憶體越界訪問,造成野指標
    }
    
    free(p1);
    
    for(i=0; i<40; i++)
    {
        p1[i] = p2[i];         // 使用已經釋放過的指標
    }

    return 0;
}
輸出:
段錯誤

基本原則

  • 絕不返回區域性變數和區域性陣列的地址
  • 任何變數在定義後必須 0 初始化
  • 字元陣列必須確認 0 結束符後才能成為字串
  • 任何使用與記憶體操作相關的函式必須指定長度資訊

例項分析: 無處不在的野指標

#include <stdio.h>
#include <string.h>
#include <malloc.h>

struct Student
{
    char* name;
    int number;
};

char* func()
{
    char p[] = "D.T.Software";
    
    return p;                    // 返回區域性陣列,warning
}

void del(char* p)
{
    printf("%s
", p);
    
    free(p);
}

int main()
{
    struct Student s;            // 指標成員沒有初始化,造成野指標
    char* p = func();            // 返回區域性陣列,造成野指標
    
    strcpy(s.name, p);           // 使用野指標
    
    s.number = 99;
    
    p = (char*)malloc(5);
    
    strcpy(p, "D.T.Software");   // 記憶體訪問越界
    
    del(p);
    
    return 0;
}

小結

記憶體錯誤是實際產品開發中最常見的問題,然而絕大多數的 bug 都可以通過遵循基本的程式設計原則和規範來避免

因此,在學習與使用的時候要牢記和理解記憶體操作的基本原則,目的和意義。

以上內容參考狄泰軟體學院系列課程,請大家保護原創!

相關文章