2017-04-08 177 views
1

我遇到了內存泄漏的巨大問題,我不知道在哪裏把這個「刪除」來擺脫它們。以下是我的代碼的一部分,並有一個完整的:https://pastebin.com/Wtk83nuH如何防止這些內存泄漏?

string* startowa(int& rozmiar) 
{ 
rozmiar = 5; 
string* tablica = new string[rozmiar]; 

for (int i = 0; i < rozmiar; i++) 
    tablica[i] = "text"; 
return tablica; 
} 

string* plusx(string* tab, int& rozmiar) 
{ 
string tekst = "something"; 
string* tablica_3 = new string[rozmiar]; 
tablica_3[rozmiar - 1] = tekst; 
for (int i = 0; i<rozmiar - 1; i++) 
    tablica_3[i] = tab[i]; 

return tablica_3; 
} 

string* minusx(string* tab, int& rozmiar) 
{ 
string* tablica_3 = new string[rozmiar]; 
for (int i = 0; i < rozmiar; i++) 
    tablica_3[i] = tab[i]; 

return tablica_3; 
} 

int main() 
{ 
int wybor = 1, rozmiar = 1; 
string *tablica = startowa(rozmiar); 

while (wybor != 55) { 
    cin >> wybor; 
    if (wybor == 1) { 
     rozmiar++; 
     tablica = plusx(tablica, rozmiar); 
    } 
    if (wybor == 6) wybor = 55; 
    else { 
     rozmiar--; 
     tablica = minusx(tablica, rozmiar); 
    } 
    // there were other "ifs" but its just a part of the code 
} 
for (int i = 0; i < rozmiar; i++) 
    cout << tablica[i] << endl; 

delete[] tablica; 
cin >> wybor; 

getchar(); 

return 0; 
} 
+4

愚蠢的,但準確的答案:不使用原始動態內存。沒有看到任何需要快速瀏覽的內容。 – user4581301

+4

切勿在C++中使用'new'。 –

+0

用std :: vector替換動態數組。如果你仍然需要指針,用std :: unique_ptr替換原始指針。現在在C++中很少需要新的/刪除,你應該在使用它們之前考慮一下。 –

回答

2

內存泄漏是您在源代碼中遇到的最少問題。實際上,在你的例子中你根本不需要堆分配。

這裏有一些快速改進:
- 使用「的std :: string」,而不僅僅是字符串,我猜您正在使用「使用命名空間std」
- 不返回一個指向字符串,你可以聲明一個字符串,並將其返回
- 如果你沒有返回它
不使用引用爲int作爲函數參數 - 使用常量,就像你可以
- 替換「字符串*」與「常量字符串&」如果你沒有返回它
- 不要在堆上分配字符串(用新的),而是在棧上聲明它
- 使用矢量

您可以使用此great site和斯科特邁耶斯書籍的其他C++良好做法。

2

爲了防止類似的內存泄漏,避免手動內存管理。有很多工具可供你使用。

例如,把你的字符串數組:

string* startowa(int& rozmiar) { 
    rozmiar = 5; 
    string* tablica = new string[rozmiar]; 

    // ... 
} 

這應該std::vector更換。而且,由於它的大小的矢量跟蹤,你不需要大小通作參考:

std::vector<std::string> startowa() { 
    // ... 
    std::vector<std::string> tablica(5); 

    // ... 
} 

然後,你的陣列上運行應參照採取矢量約拷貝功能,和返回另一個矢量。由於載體已經具有插入一個新元素的功能,你plusx函數變爲這樣:

void plusx(std::vector<std::string>& tab) { 
    std::string tekst = "something"; 
    tab.emplace_back(std::move(tekst)); 
} 

而且你minusx函數變爲:

void minusx(std::vector<std::string>& tab) { 
    tab.pop_back(); 
} 

順便說一句,用向量,就可以

// Was `string *tablica = startowa(rozmiar);` 
std::vector<std::string> tablica(5, "text"); 

由於:完全由該更換電話在主刪除您startowa功能管理它的內存本身,你不需要在任何地方刪除它。


如果你不想使用矢量,你可以一直使用std::unique_ptr<std::string[]>。您代碼中的唯一區別是將tablica.get()發送到您的函數,並使用std::make_unique<std::string[]>(rozmiar)代替new std::string[rozmiar]

0

正確答案is use std::vector。例如:

vector<string> startowa(int& rozmiar) 
{ 
    rozmiar = 5; 
    vector<string> tablica(rozmiar); 

    for (int i = 0; i < rozmiar; i++) 
     tablica[i] = "text"; 
    return tablica; 
} 

請注意價值回報。不要陷入由returning by reference節省處理時間的陷阱。那vectorgoes out of scope並且在函數結束時被銷燬。有了返回的參考資料,您可以希望的最好的方式是在發生任何損壞之前,主叫方收到垃圾並崩潰。

如果按值返回vector,並且編譯器確定它不能,std::move will take care of that,體面的編譯器將消除複製。

vector也知道它有多大,不需要rozmiar

現在......出了什麼問題?讓我們來看看分配的字符串數組和存儲的指針數組中tablica代碼

int main() 
{ 
    int wybor = 1, rozmiar = 1; 
    string * tablica = startowa(rozmiar); 

startowa

while (wybor != 55) 
    { 
     cin >> wybor; 
     if (wybor == 1) 
     { 
      rozmiar++; 
      tablica = plusx(tablica, rozmiar); 

plusx分配一個新的字符串數組,對已經返回並撰寫了由startowa返回的指針的指針。 startowa的陣列現在已經有效地丟失,泄漏,因爲幾乎不可能再次找到delete[]

在作業之前,我們需要delete[] tablica;。顯然,我們不能在撥打plusx前做到這一點,因爲tablica是一個參數,所以我們需要存儲一個臨時值。

  string * temp = plusx(tablica, rozmiar); 
      delete[] tablica; 
      tablica = temp; 

但如果意想不到的事情發生了什麼和an exception is thrown?代碼從未擊中delete[],並且兩個分配都丟失。 vector爲您處理所有這些。

而回到代碼

 } 
     if (wybor == 6) 
      wybor = 55; 
     else 
     { 
      rozmiar--; 
      tablica = minusx(tablica, rozmiar); 

同樣的問題和解決方案如上述。

 } 
     // there were other "ifs" but its just a part of the code 
    } 
    for (int i = 0; i < rozmiar; i++) 
     cout << tablica[i] << endl; 

    delete[] tablica; 

這裏發佈了一個不確定數量的分配。其餘的都丟失了。

cin >> wybor; 

    getchar(); 

    return 0; 
}