2015-12-14 9 views
6

これはC++入門、18章から運動ですスロー:メモリ私たちが直接管理しているため、上記のコードは、メモリリークを引き起こす方法メモリリークを回避するために、例外が

void exercise(int *b, int *e) 
{ 
    vector<int> v(b, e); 
    int *p = new int[v.size()]; 
    ifstream in("ints"); 
    // exception occurs here 
} 

(すなわちp)が自動的にではありません例外が発生すると解放されます。

練習18.3:

例外がスローされた場合、正しく前のコードを動作させるためには、2つの方法があります。それらを記述して実装してください。

私たちは、この落とし穴を避けるために、スマートポインタを使用することができます知っている:

void exercise(int *b, int *e) 
{ 
    vector<int> v(b, e); 
    unique_ptr<int[]> p(new int[v.size()]); 
    ifstream in("ints"); 
    // exception occurs here 
} 

か:

void exercise(int *b, int *e) 
{ 
    vector<int> v(b, e); 
    shared_ptr<int> p(new int[v.size()], [](int *p){ delete[] p; }); 
    ifstream in("ints"); 
    // exception occurs here 
} 

私はこれらがTWO方法があるかはわかりません。結局、彼らは事実上同じです。だから私は、別の方法を考えた:

void exercise(int *b, int *e) 
{ 
    vector<int> v(b, e); 
    int *p = new int[v.size()]; 
    ifstream in("ints"); 
    // exception occurs here 
    if(!in) 
     throw p; 
} 

// caller 
try { 
    exercise(b, e); 
} catch (int *err) { 
    delete[] err; // initialize err with b and delete e. 
} 

例外が発生した場合は、別のポインタを初期化し、その1を削除するpを投げます。私は完璧な解決策ではないことを知っています。なぜなら、他の例外が発生して、pを投げる機会さえもないからです。しかし、私はより良いものを考えることはできません。第二の方法を見つけるのを助けてくれますか?

+1

関数内のすべて( '...')の単純なtry-catchについてはどうですか?それを削除して、そこに戻ってください。 ...あるいは、 'p'のためにベクトルを使うのはどうですか? – deviantfan

+0

ああ、はい、この問題のために 'rethrow'がはるかに優れています。ありがとうございました! – chihyang

+1

あなたは 'ベクトル p(v.size());'を忘れています。 –

答えて

4

あなたは明示的に例外をキャッチして再スローすることができます:もちろん

void exercise(int *b, int *e) 
{ 
    vector<int> v(b, e); 
    int *p = new int[v.size()]; 
    try { 
     ifstream in("ints"); 
     // exception occurs here 
    } catch (...) { 
     delete[] p; 
     throw; 
    } 
    delete[] p; 
} 

をあなたが自由のために複数のリソースを持っている場合は、ネストされたのtry/catchブロックで終わる可能性があるため、これは、とてもうまく動作しません。 。 1つのnewに対して2つのdeleteがあることは言うまでもありません。だからRAIIが好ましい。

関連する問題