安全問題與指針誤用
聲明和初始化指針(初始化失敗)
誤用指針
釋放問題
指針聲明:
// 宏定義(僅僅是替換)
#define PINT int*;
PINT ptr1, ptr2;其實是定義 int* ptr1, ptr2;一個指針,一個整型常量。
//typedef 命名已有數據類型(優於宏定義)
typedef int* PINT;
PINT ptr1, ptr2;
宏定義和typedef區別參考:淺談c/c++typedef和#define區別
// 宏定義 和 typedef區別
#include<stdio.h> #define INTPTR1 int* int main() { typedef int* INTPTR2; int a=1; int b=2; int c=3; const INTPTR1 p1=&a;//指針常量,不可修改指向變量的值,但可以改變指向其他變量 const INTPTR2 p2=&b;//常量指針,只讀,可修改指向變量的值。 INTPTR2 const p3=&c;//常量指針,只讀,可修改指向變量的值。 printf("%d %d %d\n",*p1,*p2,*p3); printf("a=%d b=%d c=%d\n",a,b,c); p1=&c; *p2=9; *p3=10; printf("%d %d %d\n",*p1,*p2,*p3); printf("a=%d b=%d c=%d\n",a,b,c); return 0; }
使用指針之前未初始化指針(野指針)
處理未初始化指針(不可只依靠檢查指針的內容來判斷它是否有效)
總是用NULL來初始化指針
用assert函數(用來測試指針是否為空值);assert(pi!=NULL);
若為空值,輸出:Assertion failed: pi!=NULL;
用第三方工具
指針的使用問題
緩沖區溢出的幾個原因:
訪問數組元素時沒有檢查索引值
對數組指針做指針算術運算時不夠小心
用gets這樣的函數從彼岸准輸入讀取字符串
誤用strcpy和strcat這樣的函數;
測試NULL
用malloc這類函數時一定要檢查返回值,否則可能會導致程序非正常終止。
迷途指針(釋放指針後卻仍然在引用原來的內存,就會產生迷途指針)
超過數組邊界訪問內存
用下標計算的地址不會檢查索引值。
錯誤計算數組長度
將數組傳遞給函數時,一定要同時傳遞數組長度,這個信息幫助函數避免越過數組邊界。
#include<stdio.h> #include<stdlib.h> #include<string.h> void replace(char buffer[],char replacement,size_t size){ size_t count = 0; while(*buffer!=NULL && count++ <size){ *buffer = replacement; buffer++; } } int main() { char name[8]; strcpy(name,"Alexander"); replace(name,'+',sizeof(name)); printf("%s\n", name); printf("%d\n", sizeof(name)); }
錯誤使用sizeof操作符
#include<stdio.h> #include<stdlib.h> #include<string.h> int main() { int name[20]; int *pbuffer= name; for(int i=0;i<sizeof(name)/sizeof(int);i++) { *(pbuffer++)=0; } printf("%d\n", sizeof(name)); }
一定要匹配指針類型
總是用合適的指針類型來裝說句是個好主意。
有界指針
有界指針是指指針的使用被限制在有效的區域內。比如說,現在有一個32個元素的數組,禁止對這個數組使用的指針訪問數組前面或後面的任何內存。
字符串的安全問題
字符串相關的安全問題一般發生在越過字符串末尾寫入的情況。
指針算術運算和結構體
只對數組使用指針算術運算,因為數組肯定分配在連續的內存塊上,指針算術運算可以得到有效的偏移量。不過,不應該將它們用在結構體內,因為結構體的字段可能分配在不連續的內存區域。
函數指針的問題
內存釋放問題
重復釋放
清除敏感數據(在釋放內存之前將敏感數據清空)
小結: