指標的記憶體釋放
阿新 • • 發佈:2019-01-27
好幾年沒用C/C++了,由於專案需要,重拾C/C++,使用中時不時的有種親切感湧來。由於C/C++的自由,讓人痛苦但更是讓人喜歡的原因,一些經驗和技巧顯得尤為重要。
// itemName:元素名
// buff:查詢緩衝區
// return:value字串char* XmlPack::getElementValue(char* itemName, char* buff)
{
staticchar value[64];
int itemLen = strlen(itemName);
char* itemStart =newchar[itemLen +3];
memset(itemStart, '\0', itemLen +3);
itemStart[0] ='<';
itemStart[itemLen +1] ='>';
strncpy(itemStart+1*sizeof(char), itemName, itemLen);
char* itemEnd =newchar[itemLen +4];
memset(itemEnd, '\0', itemLen +4);
itemEnd[0] ='<';
itemEnd[1] ='/';
itemEnd[itemLen +2] ='>';
strncpy(itemEnd +2*sizeof(char), itemName, itemLen);
char* pos1 = strstr(buff, itemStart);
if(pos1 != NULL)
{
pos1 += strlen(itemStart);
char* pos2 = strstr(pos1, itemEnd);
if(pos2 != NULL)
{
assert((unsigned int)(pos2-pos1)<sizeof(value));
memset(value, '\0', sizeof(value));
strncpy(value, pos1, pos2-pos1);
delete[] itemStart;
delete[] itemEnd;
return value;
}
}
delete[] itemStart;
delete[] itemEnd;
return NULL;
}
最近總是想不明白,一個函式返回一個記憶體或者物件的指標,那麼這個指標指向的物件(記憶體)到底由誰來釋放?要知道,函式返回指標,通常是給外部臨時使用的,其指向的記憶體通常由函式或者成員函式所在的物件自己來管理,其實就是遵從一個原則:自己的事自己做。
如果返回一個函式中的臨時變數地址,很顯然,當執行return後,出了臨時變數的作用區,變數將被銷燬,這個指標指向的記憶體就被釋放掉了,系統可能在任何時候修改它,這個指標實際變成了野指標,外部使用它是相當危險的;
如果函式是個類的成員函式,我們能想到的是在物件中申明一個指標,由物件來管理它,成員函式只管使用,但問題是,如果有很多這樣的函式,豈不是有很多這樣的、只為函式存在的一些奇奇怪怪的指標?
實際上,解決辦法很簡單——使用靜態變數!——前面不是空了,而是白了,想看的,自己先想想答案,然後再想辦法看吧 :0
來段程式碼:
// 取得Xml元素的值// itemName:元素名
// buff:查詢緩衝區
// return:value字串char* XmlPack::getElementValue(char* itemName, char* buff)
{
staticchar value[64];
int itemLen = strlen(itemName);
char* itemStart =newchar[itemLen +3];
memset(itemStart,
itemStart[0] ='<';
itemStart[itemLen +1] ='>';
strncpy(itemStart+1*sizeof(char), itemName, itemLen);
char* itemEnd =newchar[itemLen +4];
memset(itemEnd, '\0', itemLen +4);
itemEnd[0] ='<';
itemEnd[1] ='/';
itemEnd[itemLen +2] ='>';
strncpy(itemEnd
char* pos1 = strstr(buff, itemStart);
if(pos1 != NULL)
{
pos1 += strlen(itemStart);
char* pos2 = strstr(pos1, itemEnd);
if(pos2 != NULL)
{
assert((unsigned int)(pos2-pos1)<sizeof(value));
memset(value, '\0', sizeof(value));
strncpy(value, pos1, pos2-pos1);
delete[] itemStart;
delete[] itemEnd;
return value;
}
}
delete[] itemStart;
delete[] itemEnd;
return NULL;
}
但是需要特別注意的是,使用區域性靜態變數是執行緒不安全的,是一個不可重入函式。
解決這個問題的標準、權威的做法還是呼叫者提供儲存空間,通過引數傳入地址,這樣,呼叫者可以使用區域性變數來獲取處理結果。這種方式麻煩,但是權威。下面一段文字來自Sun公司對多執行緒模型的討論(《多執行緒程式設計指南》• 2006年10月,P231, 所有權歸Sun公司所有):