【C】內存操做經典問題分析一

野指針

指針變量中的值是非法的內存地址,進而造成野指針
野指針不是NULL指針,是指向不可用內存地址的指針
NULL指針並沒有危害,很好判斷,也很好調試
C語言中沒法判斷一個指針所保存的地址是否合法

野指針的由來

局部指針變量沒有初始化
指針所指向的變量在指針以前被銷燬
使用已經釋放過的指針
進行了錯誤的指針運算
進行了錯誤的強制類型轉換

例子41-1:編程

#include"stdio.h"
#include"malloc.h"
int main()
{
    int*p1 = (int*)malloc(40);
    int*p2 = (int*)1234567;  //整型值強制類型轉化爲指針類型,錯誤的強制類型轉化
    int i = 0;                    
    printf("%p\n",p1);
    for(i = 0;i < 40;i ++)
    {
        *(p1 + i) = 40 - i;   //40個字節只有十個整型,循環40次,40*4 = 160個整型,動態內存不夠
    }                          //因爲指針運算產生了野指針,改寫了非法的內存地址
    free(p1);
    printf("%p\n",p1);
    for(i = 0;i < 40;i ++)
    {
        p1[i] = p2[i];       //使用了已經釋放的內存空間
    }

    return 0;
}

輸出結果:
錯誤
修改後正確代碼:數組

#include"stdio.h"
#include"malloc.h"
int arr[40] = {1,2,3,4,5,6,7};
int main()
{
    int*p1 = (int*)malloc(40*sizeof(int));
    int*p2 = (int*)arr;  
    int i = 0;                    
    printf("%p\n",p1);
    for(i = 0;i < 40;i ++)
    {
        *(p1 + i) = 40 - i; 
    }                        
    free(p1);
    p1 = NULL;
    printf("%p\n",p1);
    for(i = 0;i < 40;i ++)
    {
        p1[i] = p2[i];      
    }
    return 0;
}

輸出結果:函數

00931260
00000000

基本原則

毫不返回局部變量和局部數組的地址
任何變量在定義後必須0初始化(指針變量初始化爲空指針NULL)
字符數組必須確認0結束符後才能成爲字符串
任何使用與與內存操做相關的函數必須指定長度信息

例子41-2:指針

#include "stdio.h"
#include "malloc.h"
#include "string.h"
struct Student
{
    char* name;
    int number;
}
char* func()
{
    char p[] = "D.T.Software";
    return p;
}
void del(char* p)
{
    printf("%s\n",p);
    free(p);
}
int main()
{
    struct Student s; //因爲沒有初始化,產生野指針
    char* p =func();//產生了野指針
    strcpy(s,name,p);//使用了野指針
    s.name = 99;
    p = (char*)malloc(5);
    strcpy(p,"D.T.Software");//產生內存越界,操做了野指針所指向的內存空間
    del(p);
    return 0;
}

小結:

內存錯誤是實際產品開發中最多見的問題,然而絕大多數的bug均可以經過遵循基本的編程原則和規範來避免。調試

相關文章
相關標籤/搜索