2017-04-08 116 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; 
}