2017-04-08 23 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に置き換えてください。 new/deleteはC++ではほとんど必要とされず、使用する前に考えるべきです。 –

答えて

2

メモリリークは、そのソースコードでの問題ではありません。実際、あなたの例ではヒープ割り当ては一切必要ありません。ここで

いくつかの速い改善されている:
- だけではなく、文字列の「のstd :: string」を使用し、私はあなたが「名前空間stdを使用して、」使用していると思います
- 文字列へのポインタを返さない、あなただけ宣言することができますそれ
文字列と返す - あなたはそれを
を返されていない場合は、関数のパラメータとしてint型への参照を使用していない -
あなたはできる限り使用ポーラ - 「CONST文字列&」と「*文字列を」交換してください
- ヒープに文字列を割り当てないでください(新しいもの)。代わりにスタックに宣言してください
- 使用ベクター

このgreat siteとScott Meyersの書籍は、他の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()を関数に送り、new std::string[rozmiar]

0

の代わりにstd::make_unique<std::string[]>(rozmiar)を使用することです。正解は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を呼び出す前にこれを行うことはできませんので、一時的なものを保存する必要があります。

  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; 
} 
関連する問題