野指標通常是因為指標變數中儲存的值不是乙個合法的記憶體位址而造成的。
1.在堆空間動態申請的;
2.區域性變數所在的棧。
野指標不是null指標,是指向不可用記憶體的指標,也可能是乙個動態的記憶體位址,但是這個記憶體別人正在使用,這也是不合法的位址。
null指標不容易用錯,因為if語句很好判斷乙個指標是不是null。c語言中沒有任何手段可以判斷乙個指標是否為野指標!
野指標的由來
1.區域性指標變數沒有被初始化;
#include
#include
struct student
char* name;
int number;
int main()
struct student s;
strcpy(s.name, "delphi tang"); // oops!
s.number = 99;
return 0;
區域性變數沒有被初始化,指標name指向的記憶體空間位址是隨機的,當然不能向隨機位址空間寫資料。
2.使用已經釋放過後的指標;
#include
#include
#include
void func(char* p)
printf("%s\n", p);
free(p);
int main()
char* s = (char*)malloc(5);
strcpy(s, "delphi tang");//陣列越界
func(s);
printf("%s\n", s); // oops!使用已經釋放的指標s
return 0;
釋放一片指標後,意味著把這片記憶體歸還到空閒鍊錶,歸還意味著其它程式可以使用這片空間,
如果寫了其它程式使用的空間,可能導致其它程式莫名其妙的被關閉。
3.指標所指向的變數在指標之前被銷毀。
#include
char* func()
char p = "delphi tang";
return p;
int main()
char* s = func();
printf("%s\n", s); // oops!
return 0;
函式呼叫的時候,在棧區存放區域性變數,p是區域性陣列,放在活動記錄裡面,func返回之後,
棧頂指標退出,活動記錄占用記憶體已經被釋放掉,s指向乙個被釋放掉了棧空間,如果棧空間值被修改了,
就不會列印出預期結果,s是個野指標。
非法記憶體操作分析
1.結構體成員指標未初始化
2.沒有為結構體指標分配足夠的記憶體
#include
#include
struct demo
int* p;
int main()
struct demo d1;
struct demo d2;
int i = 0;
for(i=0; i<10; i++)
d1.p[i] = 0; // oops!結構體指標未初始化
d2.p = (int*)calloc(5, sizeof(int));
for(i=0; i<10; i++)
d2.p[i] = i; // oops!陣列越界
free(d2.p);
return 0;
3.記憶體初始化分析
記憶體分配成功,但未初始化
int main(void)
char *s = (char*)malloc(10);
printf(s);//沒有在記憶體中填充資料,就相當然作為字串來使用,是不是字串還不一定
free(s);
return 0;
以上程式只需改寫乙個字母就會絕對正確。
4.記憶體越界分析
陣列越界
#include
void f(int a[10])
int i = 0;
for(i=0; i<10; i++)
a[i] = i; // oops!
printf("%d\n", a[i]);
int main()
int a[5];
f(a);
return 0;
5.記憶體洩露
#include
#include
void f(unsigned int size)
int* p = (int*)malloc(size*sizeof(int));
int i = 0;
if( size % 2 != 0 )
return; // oops!出口1,還沒有釋放記憶體就結束
for(i=0; ip[i] = i;
printf("%d\n", p[i]);
free(p);//出口2
//f函式有乙個入口,兩個出口,最好「單入口,單出口」
int main()
f(9);
f(10);
return 0;
修改後「單入口,單出口」
#include
#include
void f(unsigned int size)
int* p = (int*)malloc(size*sizeof(int));
int i = 0;
if( size % 2 == 0 )
for(i=0; ip[i] = i;
printf("%d\n", p[i]);
free(p);
int main()
f(9);
f(10);
return 0;
6.多次釋放指標
會導致異常退出
#include
#include
void f(int* p, int size)
int i = 0;
for(i=0; ip[i] = i;
printf("%d\n", p[i]);
free(p);//釋放
int main()
int* p = (int*)malloc(5 * sizeof(int));
f(p, 5);
free(p); // oops!二次釋放
return 0;
解決方法:誰申請誰釋放,在main中申請就在main中釋放。
以上程式也可以採取這樣的解決方法,在f函式中增加第三個引數,然後在main中決定是否釋放
#include
#include
void f(int* p, int size,int tofree)
int i = 0;
for(i=0; ip[i] = i;
printf("%d\n", p[i]);
if(tofree)
free(p);//釋放
int main()
int* p = (int*)malloc(5 * sizeof(int));
f(p, 5,0);
free(p); // oops!二次釋放
return 0;
7.使用已釋放的指標
#include
#include
void f(int* p, int size)
int i = 0;
for(i=0; iprintf("%d\n", p[i]);
free(p);
int main()
int* p = (int*)malloc(5 * sizeof(int));
int i = 0;
f(p, 5);//在函式f中已經釋放p指向的記憶體
for(i=0; i<5; i++)//而又在此處操作p所指向的記憶體,p是野指標。
p[i] = i; // oops!
return 0;
c語言中的交通規則(我們自己約定的規則,可以避免錯誤)
1.用malloc申請了記憶體之後,應該立即檢查指標值是否為null,防止使用值為null的指標;
這樣可以杜絕操作0記憶體位址的內容,0記憶體位址是非常特殊的位址,是作業系統所使用的。
int *p = (int*)malloc(5 * sizeof(int));
if( p != null )
//do something here!
free(p);
2.牢記陣列的長度,防止陣列越界操作,考慮使用柔性陣列;
typedef struct _soft_array
int len;
int array;
}softarray;
int i = 0;
softarray *sa = (softarray*)malloc(sizeof(softarray) + sizeof(int)*10);
sa->len = 10;
for(i=0; ilen; i++)
sa->array[i] = i+1;
3.動態申請的操作必須和釋放操作匹配,防止記憶體洩露和多次釋放
void f()
int *p = (int*)malloc(5);
free(p);
int main()
int *p = (int*)malloc(10);
f();
free(p);;
return 0;
4.free指標之後必須立即賦值為null
int *p = (int*)malloc(10);
free(p);
p = null;
if(p != null)
int i = 0;
for(i=0; i<5; i++)
p[i] = i;
野指標與非法記憶體操作
野指標 野指標通常是因為指標變數中儲存的值不是乙個合法的記憶體位址而造成的。1.在堆空間動態申請的 2.區域性變數所在的棧。野指標不是null指標,是指向不可用記憶體的指標,也可能是乙個動態的記憶體位址,但是這個記憶體別人正在使用,這也是不合法的位址。null指標不容易用錯,因為if語句很好判斷乙個...
記憶體操作 野指標
試題4 void getmemory char p void test void 試題5 char getmemory void void test void 試題6 void getmemory char p,int num void test void 試題7 void test void 解答...
記憶體洩漏與野指標
當你要為變數a申請一塊記憶體空間的時候,需要用到malloc函式。如何申請這塊記憶體空間呢?這就變成程式的工作了。程式首先會向系統申請一塊記憶體空間,然後程式會把申請好的這塊記憶體空間的首位址賦給變數a,假設這時候變數a拿到的首位址為0x1234,如果我們現在要對變數a進行迴圈操作,那麼每迴圈一次,...