2011-02-01 110 views
2

私はこの2D Qlistを作成しました。コードは機能しますが、シンタックスを少し深く考えてみると、このコードがメモリリークを引き起こすかどうかはわかりません。2d QListメモリリーク

誰かがこのコードがmemのリークにつながるかどうかを明らかにすることができたら嬉しいです。それがあれば、なぜ、どのように修正するのですか?

私の懸念事項は、コードコメントでQ1、Q2、Q3、Q4とマークされている質問です。

また、どのようにlszq2DListからいくつかの行を破壊する必要があります。最終的にどのように破壊するべきですか? lszq2DList

//The 2d data sructure. Each row will be a QStringList. 
QList<QStringList> lszq2DList; 

//The variable "emptyTempList" is a concern to me. 
//Q1:: Isn't "emptyTempList" just a pointer to some allocated place in memory? 
//If so, I imagine it points to some data structure allocated in memory. 
//Or does this not allocate anything? I have a feeling it does not. 
QStringList emptyTempList; //I use it in my scheme to make a 2D data struct. 

for(int i=0; i<3; i++){ 
    //Q2: Because I am in a loop and reusing the same pointer "emptyTempList", 
    //aren't i pointing to the same thing? 
    //If I think about this, each item in my Qlist (each row) should be 
    //pointing to the same place in memory. To whatever "emptyTempList" 
    //points to.  
    //Of course, this is not the case. What is really going on in line bellow? 
    lszq2DList += emptyTempList; //I'm no really pointing to anything am I? 

    QString szqTempString; //Q3: Gets trashed when out of scope? 
    for(int j=0; j<3; j++){ 
     szqTempString.clear(); 
     szqTempString = "jazz"; 

      //QString value gets copied into datastructure? 
     lszq2DList[i] += szqTempString; 
    } 
} 


QStringList emptyTempList2; 
emptyTempList2 += "blues"; 
emptyTempList2 += "blues"; 
emptyTempList2 += "blues"; 

//I'll add another row. 
lszq2DList += emptyTempList2; 
//Q4: lszq2DList[3] does not point to emptyTempList2, right? 
//Instead it copies all the strings 
//from to emptyTempList2 to lszq2DList[3], right? 
+3

投稿されたコードにはメモリ割り当てもありません。どのように漏れがありますか? –

答えて

3

私は、valgrindなどのようなものを使用してメモリリークを調べることをお勧めします。

しかし、メモリが "リーク"すると、メモリが使用後に解放されず、すべてのアクセスが削除されたことを意味します。これは、本質的に、ヒープ上に割り当てられたメモリがあることを意味しますが、何もアクセスしていないので、事実上無駄なメモリです。たとえば、 "new"を使用してポインタに動的にメモリを割り当てる場合、メモリが解放されるように "delete"する必要があります。私は例を挙げます。

char * ptr = new char; 
ptr = NULL; // Memory leak 
delete ptr; // This is useless since it no longer points to the memory location 

しかし、これはあなたがメモリを「削除」しなかったので、最初の1曲の漏れがある

char * ptr = new char; 
delete ptr; 
ptr = NULL; 

理由は全く有効です。削除が呼び出される前にポインタの位置が "NULL"に変更されたため、の前にポインタに関連付けられていたアドレスを空きにすることを知らなかった。

しかし、あなたのコードにメモリリークがあるようには見えません(何も動的に割り当てられていません)。すべての変数がスタック上に割り当てられているように見えるので、システムはこのメモリを管理します - これらのオブジェクトがスコープから外れると(これがmain()の場合、プログラムが終了すると)スタックからポップされます。システム。しかし、これは、QListが漏れていないと仮定しています。

EDIT

は、クラスのインスタンスを作成するときに、割り当てられたメモリがスタックにある、覚えておいてください(メモリがスコープを出る時に即座に解放された)あなたが心配する必要はありませんています。動的割り当て(新規/削除を使用したメモリの割り当て/割り当て解除)は、ヒープ(本目的のために永続メモリ)に格納されます。したがって、動的に割り当てなかったメモリのリークについては心配する必要はありません。

できるだけスタック、使用スタック対ヒープを使用することに関してはEDIT 2

。あなたが管理しなければならないメモリが少なくて済む(そして、バグが発生しにくくなります)。 2つ目の質問に関しては、ポインタを使用していません。あなたがしているのは、の値emptyTempListにコピーし、そのメモリ位置を(ポインタではないので)再利用しないことです。 &演算子を使用してオブジェクトからメモリアドレスを抽出する必要があります。これはポインタではないためです。

希望すると便利です。

よろしく、
デニスM.

+0

私は、ありがとう。私はまだQ2 ::について私のソースコードで混乱しています。それが私の混乱の根源でした。上記の例では、ファイルシステムのスキャンのように多くの情報を格納していた場合、新しいものを使用する必要があるかどうか、あなたの答えは私に尋ねます。つまり、スタック上の空き領域がなくなる可能性が高いので、代わりにヒープを使用する必要があります。 – user440297

+0

私の返答が少し追加されました。 – RageD

+0

はい、ありがとうございました。しかし、 "emptyTempList"は実際にはデータを含んでいないので、その型だけをコピーしています。それは理にかなっている。違う?私はJavaから来ており、これらのものはそこに隠されているので、そのような構文の基礎について考える必要は全くありませんでした。しかし、カトリーナのように指摘してください...実際には、これは伝統的なC-ASNIのセンス。実際には私はコード・コメントに関心があったので、ポインタ・アドレスのみをコピーしているようです。ですから、実際にはそうではないにしても、これはスレッド型のアプリケーションでさえも価値のあるコピーであるとは思わないのでしょうか? – user440297

4

QListに、QStringList、とのQStringはすべて基本的に "コピーオンライト" を意味し、 "暗黙のうちに共有" されています。たとえば、

QStringList someFunction() { 
    QStringList list; 
    QString str("Hello World!"); 

    for(int x = 0;x < 100; ++x) { 
     list << str; 
    } 

    QStringList list2 = list; 
    QStringList list3 = list; 
    QStringList list4 = list; 

    return list4; 
} 

QStringList list5 = someFunction(); 

さらに、文字列「Hello World!」だけがあります。メモリに1回。あなたはそれについてもっと読むことができますHere。 Qtクラスの一般的なルールとして、「QObjectから継承するオブジェクトはヒープになります。それ以外の場合はスタックに移動します」。例外はありますが、ほとんどまたは暗黙的に共有されるクラスは常にスタックに置かなければなりません。

+0

ありがとう、素晴らしい投稿。データへのポインタだけがurリンクに沿って渡されるため、Qtのドキュメントはそれを綴りませんが、関数urlで返される "list4"はTRUEのコピーであると仮定できます。 funcのスコープ要素のうち無効な参照を破棄することがあります。 Qt docは、あなたが "書く"ときにディープコピーをします。 Qtのドキュメントは、物事が深刻にコピーされる時期については明確ではありません。 Qtは、シンタックスがcopy by value操作を意味し、このスキームがスレッドセーフである状況では、「暗黙的な共有」を実行しないとするのは安全でしょうか? – user440297

+0

@ user440297: "return list4"は、リスト自体をコピーし、参照カウントを暗黙的に共有される内部(コピーオンライト)に増やすことによって、QStringListのコピーを作成します。 ref count == 2.スコープが残っているとき、 'list4'は破壊され、refを減少させます。カウントし、返されたコピーをあなたに残します。 ref count == 1.内部はまったくコピーされていないので、それは比較的安価な操作です。 –

+0

@ user440297基本的に深いコピーは、クラスに対して非constメソッドを呼び出すたびに作成されます。 –