1、 內存分配方式
(1)從靜態存儲區域分配。例如使用static、全局變量。靜態存儲區的數據在程序編譯的時候就已經分配好了,在程序運行期間一直存在,只有在程序推出之後才會釋放。
(2)在棧上分配。函數內部的局部變量都是在棧上分配的,在函數階數時存儲空間便被釋放;
(3)在堆上分配。程序員根據自己的需要申請和釋放內存(new/delete malloc/free)
2、在內存的分配過程中經常會出現一些錯誤。
(1)內存未分配成功卻使用了他。例如內存中沒有足夠大的剩余空間此時內存分配(new/malloc)失敗之後會返回NULL,可以用assert(p!=NULL)或者if語句進行檢查。
(2)內存分配成功卻沒有初始化就引用它。 int *p=newint(10);//忘記初始化
(3)內存分配成功,但是越界操作。在使用數組下標時容易出現“多1”、“少1”
(4)忘記釋放內存,造成內存洩露。
(5)內存被釋放(delete)之後卻繼續使用它
3、指針與數組
(1)修改內容
char a[]=”hello”;
a[0]=’X’;
cout<<a<<endl;
char *p=”world”; //這裡定義p指向常量字符串
p[0]=’X’; //錯誤,常量字符串的值不能被改變
cout<<endl;
(2)當使用數組作為函數的參數進行傳遞時,該數組自動退化為同類型的指針
void printLen(char a[100])
{
Cout<<sizeof(a)<<endl;//這裡會輸出4 而不是100
}
(3)指針參數傳遞內存
如果一個函數的參數是一個指針,不要使用該指針去申請動態內存。例如:
void getMem(char *p, int len)
{
p=(char*)malloc(sizeof(char) * len);
}
void test(void)
{
char*str=NULL;
getMem(str,1100);//執行之後str仍是NULL
strcopy(str,“hello”);//由於str=NULL 所以導致運行錯誤
}
上面運行錯誤是因為,在函數中重視要為每個參數制作一個臨時的副本,在getMem中,指針參數p的副本就是_p,在編譯器中會使_p=p。從而在函數體中修改了_p所指向的內容也就修改了p所指向的內容,這也就是指針可以作為輸出參數的根本原因。但是在getMem函數中,臨時的副本_p申請了一個新的內存空間,從而把_p所指向的空間改變了,從此再改變_p所指向的內容時,原來p所指向的內容被沒有變化。而且這裡沒有使用free函數釋放內存,從而在每次執行getMem的時候還會洩露一塊內存。
解決辦法:通過指向指針的指針 或者 返回指針
(1)指向指針的指針
void getMem1(char **p, int num)
{
*p=(char*)malloc(sizeof(char) * num);
}
void test1(void)
{
char*str = NULL;
getMem1(&str,100); //注意這裡是&str
strcpy(str,“hello”);
cout<<str<<endl;
free(str); //不要忘了釋放內存
}
(2)使用return返回指針
使用函數的返回值來動態傳遞內存的這種做法雖然比較好,但是有時候程序員常常會把return語句返回的結果弄錯掉。主要是強調不要使用return語句返回指向棧內存的指針,因為該內存在函數結束的時候將會被釋放,下次再訪問該內存空間時存儲的很可能不是原來的數據。例如:
#include "stdafx.h"
#include <iostream>
using namespace std;
char *getStr(void)
{
char str1[] = "hello world";//這個數據存儲在棧上,在這個函數階數之後這個空間將會被釋放。
//由於返回的str指向的是這個地址,在以後再次用到這個地址時
//由於str這個空間已經被分配給其他變量,所以之後對str的操作
//會出錯。
cout<<"str1[]的地址"<<&str1<<endl;
returnstr1; //這裡編譯器會提出警告,VC6.0中返回的地址為0x0012FE90
}
void test()
{
char*str2=NULL;
str2= getStr(); //這裡str2=0x0012FEF0
cout<<"str2的地址"<<&str2<<endl;
cout<<str2<<endl;//打印出來的並不是 hello world 而是一串比較亂的字符,因為並不知道str2裡面存的是什麼
}
void main(void)
{
test();
}
注釋:其實這裡可以把下面這個函數中的變量定義做些修改:
char *getStr(void)
{
char str1[] = "hello world";
}
這個函數裡的變量定義到靜態存儲區中就可以實現輸出“hello world”
例如 static char str1[] = “hello world”; 或者 char *p = “hello world”;//這裡需要注意一下第二種方法定義的是一種字符常量
作者:qingtingchen1987