2015-10-04 109 views
2

我正在學習C/C++,我正在做的練習是創建一個評估算術表達式的程序。我是否正確釋放堆中的內存?

要完成練習,我需要一個通用函數,它能夠標記一個字符串。 由於編譯時不知道要解析的字符串的大小,因此我必須動態地分配堆中的一些數據。

工作完成後,可以釋放堆中的內存。

我的問題很簡單:我正確釋放內存?查看評論中的問題。

記號化功能

char** Tokenize(const char delimiter, const char* string) 
{ 
    const char* pString = string; 
    char** tokens = new char*[strlen(string)]; 
    char* buffer = new char[strlen(string)]; 
    char* pointer = buffer; 
    int c = 0; 

    for (int k = 0; k < strlen(string); k++) 
    { 

     if (string[k] == delimiter) 
     { 
      buffer[k] = '\0'; 
      tokens[c] = pointer; 
      pointer = buffer + k + 1; 
      c++; 
      continue; 
     } 

     buffer[k] = string[k]; 
    } 

    tokens[c] = nullptr; 
    return tokens; 
} 

主要功能哪些測試記號化功能和relases堆。

int main() 
{ 
    char** tokens = Tokenize('.', "192.168.1.1"); 
    char** startTokensPointer = tokens; 
    char* startBufferPointer = *tokens; 

    while (*tokens != nullptr) 
    { 
     cout << *tokens << endl; 
     tokens++; 
    } 

    delete[] startTokensPointer; //Releases tokens?? 
    delete[] startBufferPointer; //Releases buffer?? 

    system("PAUSE"); 
} 
+1

我無法確定是否正確釋放內存。我可以告訴你,你可能會使用太多的內存,並且需要非常小心才能使其工作。只需使用'std :: string'就可以完成基本相同的任務,除非你只是從程序中刪除所有'新'和大多數指針。這種編程風格是不可維護的。 – nwp

+0

您正在使用C++語法,避免其他好東西沒有太多意義。像std :: string和std :: map。 –

+0

delete與新的匹配,但是對於使用數組的方式看起來非常不對。 ... – deviantfan

回答

0

是的,沒有內存泄漏,但爲什麼不使用保證它的類型?

struct Tokens 
{ 
    explicit Tokens(size_t len) : tokens(new char*[len]), buffer(new char[len]) 
    { } 

    std::unique_ptr<char*[]> tokens; 
    std::unique_ptr<char[]> buffer; 
}; 

Tokens Tokenize(const char delimiter, const char* string) 
{ 
    auto len = strlen(string); 
    Tokens result(len); 
    char* pointer = result.buffer.get(); 
    int c = 0; 

    for (size_t k = 0; k < len; k++) 
    { 

     if (string[k] == delimiter) 
     { 
      result.buffer[k] = '\0'; 
      result.tokens[c] = pointer; 
      pointer = result.buffer.get() + k + 1; 
      c++; 
      continue; 
     } 

     result.buffer[k] = string[k]; 
    } 

    result.tokens[c] = nullptr; 
    return result; 
} 

int main() 
{ 
    auto tok = Tokenize('.', "192.168.1.1"); 
    char** tokens = tok.tokens.get(); 

    while (*tokens != nullptr) 
    { 
     cout << *tokens << endl; 
     tokens++; 
    } 
} 

現在所有的內存都是自動管理的,幾乎不可能泄漏。

+0

我建議先幫他解決他目前的問題。鑑於他正在重新實施strtok,我猜他會試圖學習並檢查他的結果。獨特的指針很不錯,但它們不會幫助您處理任何遺留代碼 - 其中大部分代碼正在編寫當中 - 因爲它們仍然執行手動內存管理。只要你嘗試一個shared_ptr,你就會打開一個新的蠕蟲罐。 – dascandy

+0

@dascandy,我不明白這個投訴。他在分配的內存上使用'delete []',這是一種代碼味道,應該用RAII類型替換。要與傳統代碼進行交互,請使用'unique_ptr :: get()'來獲取原始指針。這與糾正內存管理和避免裸「刪除」是正交的。 –

+0

感謝您的努力,但正如我寫的,我正在學習C++(不用C++編寫實際項目)。 在瞭解低級別事物之前學習高級事物違背了我的哲學。 我會繼續爲第一個練習手動管理內存,我會記住你對未來的建議。 –

1

您沒有正確釋放buffer。如果沒有一個字符的string等於if語句delimiter代碼在此:

if (string[k] == delimiter) 

將永遠不會被執行,c將保持0。然後這條線:

tokens[c] = nullptr; 

將設置存儲在startBufferPointernullptrtokens第一個元素。在那種情況下,您正在泄漏buffer,因爲指向buffer的指針在main中「被遺忘」。

tokens在所有情況下均正確釋放。

+0

不錯,你發現了錯誤。 對:你必須注意nullptr! –