2016-11-10 11 views
2

は、シナリオ1のスタックまたはヒープでfuncVarですか?inderectヒープ割り当てのスタックまたはヒープ

私はそれが疑わしいので、私は尋ねているので、これはメモリリークを最小限に抑えるための良い方法かもしれません。つまり、シナリオ1のように間接的にヒープ上に物事を置くヒープ上の上位レベルにコードを配置する方が良いかもしれません。

シナリオ2では、決して呼ばれることはありません。シナリオ1のようにコードを使用することにより、私はシナリオのシナリオ2.

シナリオ1

class Test{ 
    int memVar = 1; 

    void func(){ 
     int funcVar = 2; 
     SomeClass::someFuncThatCouldCrash(); 
    } 
}; 

Test* t = new Test(); 

シナリオ2

class Test{ 
    int memVar = 1; 

    void func(){ 
     int* funcVar = new int(2); 
     SomeClass::someFuncThatCouldCrash(); 
     delete funcVar; //May not free due to crash in line above; 
    } 
}; 

Test t; //or Test* t = new Test() 
+0

このコードの目的は明確ではありません。 'funcVar'はそれに割り当てられた値を除いて決して使用されません。' someFuncThatCouldCrash'はそれを変更しません。 – Xirema

+0

ありがとう、iircとRyanP、私はより明確になるようにコードを整理しました。 Xiremaは、このコードは有用なことをしません、私はそれをきれいに保つために、配分とメモリクリーンアップに集中していました。 – code

+0

_シナリオ1のスタックまたはヒープにfuncVarがありますか?誰かがスタックでもヒープでもないと言います。 – skypjack

答えて

1

のように(排除しない)の問題を最小限に抑えることを望みます1 funcVarint funcVar = 2と仮定)はfunc()が呼び出されたときにスタックにあり、シナリオ2ではヒープ上にあります。あなたは正しいです。someFuncThatCouldCrashが例外を投げた場合、それは決して削除されません。

また、シナリオ2ではfuncVarを削除して返します。これはうまくありません。また、その場合、戻り値の型が通常のintであるときにポインタを返します。

C++ 11では、生のnewとdeleteを処理する必要はありません。基本的には、ほとんどすべてがスタック上の変数でなければなりません。ヒープ割り当てが必要な場合は、内部的にヒープ割り当てを管理するスタック上のローカル変数であるベクトルのようなものを使用します。そのようにして、ベクトルが範囲を越えると、それは削除を呼び出すことなくそれ自体をクリーンアップします。 RAII(リソース割り当ては初期化)と呼ばれ、さらにルックアップしたい場合に使用します。

オブジェクトへのポインタが必要な場合(基本クラスポインタを使用してポリモーフィックオブジェクトを保持する、または一般的に大きなクラスのインスタンスを作成するなど)、std::unique_ptrは基本的にそのローカル変数を作成します作成したオブジェクトのdeleteを呼び出します。まれに、std::shared_ptrが必要な場合もありますが、それが何であり、なぜ必要なのかを調べることができます。

+0

Hmmm ...シナリオ1では、memVarはヒープ上にありますが、funcVarはスタック上にあります。これは正しいですか?私は、memVarがシナリオ1で間接的にヒープにプッシュされるため、その関数の "コールスタック"もヒープにプッシュされると想定していましたが、そうは思いません。 – code

+0

@codeシナリオ1では、テスト 't'のインスタンスがヒープ上にあります。したがって、' memvar'(やはり型が必要です)はヒープ上のそのオブジェクトの一部になります。 'func()'を呼び出すと、それは呼び出しスタック上の関数になり、そのすべてのローカル変数( 'funcVar'を含む)はそのスタックフレームの一部です。 – RyanP

+0

を参照してください。だから、実際には、std :: unique_ptrやstd :: shared_ptrを使わずにシナリオ2のようなメモリリークを避けるための巧妙な方法はないと言いますか? – code

0

最初のシナリオでは、スタックに割り当てられます。 2番目のシナリオでは、ヒープ上に割り当てられ、SomeClass::someFuncThatCouldCrashから例外がスローされて、スタックの上位にキャッチされた場合はリークすることが正しいです。

メモリの安全性を確保しながら動的割り当てを使用する場合は、使用例に応じてstd::unique_ptrまたはstd::shared_ptrを使用する必要があります。

0

自動ストレージのローカル変数は「スタック」にあります。

クラスメンバ変数は、クラスのインスタンスが "スタック"または "ヒープ"にあるかどうかに応じて、 "スタック"または "ヒープ"にあります。

静的ローカルおよび静的クラスメンバー変数を含むグローバルデータは、「スタック」または「ヒープ」のいずれにもありません。

スレッドローカルデータは「スタック」または「ヒープ」にはありませんが、ヒープに実装されている可能性があります。

したがって、シナリオ1はローカル変数としてfuncVarを持ちます。したがって、「スタック」にあります。クラスTestのインスタンスはヒープ上にあります。

シナリオ2では、funcVarは「スタック」に残りますが、は、が「ヒープ」上のものです。確かに例外的な安全性はありません。例外がスローされると、リークする可能性があります。クラッシュは、ほぼすべてのオペレーティングシステム上の「残された」単純なメモリリソースをクリーンアップすることになります。プロセス終了時にリサイクルされない場合がありますが、状況によってはまたはnewが返ってくるものではない場合があります。

std::unique_ptrおよびstd::make_uniqueを使用すると、ほとんどすべてのそのようなリークが緩和されます。現代のC++では、型システムで明示的に所有されていない未処理のポインタ割り当てやメモリリソースを避けることは、一般的には良い考えです。

関連する問題