簡體   English   中英

如何防止這些內存泄漏?

[英]How can I prevent these memory leaks?

我遇到了內存泄漏的巨大問題,而且我不知道在哪里放置該“刪除”以消除它們。 以下是我的代碼的一部分,有完整的代碼: 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;
}

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

以下是一些快速改進:
-使用“ std :: string”而不是字符串,我猜您正在使用“使用命名空間std”
-不要返回指向字符串的指針,您只需聲明一個字符串並返回它
-如果不返回int,請勿將其用作函數參數
-盡可能多地使用const
-如果不返回,請用“ const string&”替換“ string *”
-不要在堆上分配字符串(使用new),而是在堆棧上聲明它
-使用載體

您可以使用這個很棒的網站和Scott Meyers的書來獲取其他C ++良好實踐。

為避免此類內存泄漏,請避免手動進行內存管理。 有很多工具可供您使用。

例如,使用您的字符串數組:

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();
}

順便說一句,使用向量,您可以通過以下方式替換main中的調用來完全刪除startowa函數:

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

由於std::vector本身管理內存,因此您無需在任何地方刪除它。


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

正確的答案是使用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;
}

注意按值返回。 不要陷入以為通過引用返回來節省處理時間的陷阱。 vector 超出范圍,並在函數末尾銷毀。 使用返回的參考,您最好的希望是呼叫者在造成任何損害之前會收到大量的垃圾並崩潰。

當您按值返回vector時,體面的編譯器將消除復制,如果編譯器決定不能這樣做,則std::move將解決該問題

vector也知道它有多大,從而消除了對rozmiar的需要。

現在...出了什么問題? 讓我們看一下代碼

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

startowa分配一個字符串數組,並存儲一個指向在陣列tablica

    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;

但是,如果發生意外情況並引發異常怎么辦? 代碼永遠不會碰到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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM