
よろしくお願いします。
クラスのメンバで3つのlongのポインタを宣言し、
コンストラクタ内でそれぞれにnewして領域を確保
しています。
質問1)newを失敗した場合には、そのポインタに
対してdeleteしてはいけないのでしょうか?
質問2)上記3つもエリアの確保のうち、2つめで失 敗した場合、1つ目のdeleteをしてやる
必要はあるのでしょうか?
catch(bad_alloc)でその処理をしようとおもうのですが、そもそもコンストラクタで例外を発生させるなと
かかれている書籍もあるようです。ただ、すでにそういう記載になってしまっており、できれば、いまの構造でメモリーリークを防げないかと思案しております。どなたか、よい方法をご存知の方いらっしゃいましたら、アドバイスいただけましたら幸いでございます。
No.4ベストアンサー
- 回答日時:
#2です。
> たとえば、bのnewでアロケーションを失敗した場合、
> Cのポインタは0で初期化された状態で、deleteしても
> 問題ないのでしょうか?
> また、Bのnewで失敗した状態のBにもdeleteを実行することになりますが、問題ないのでしょうか?
> deleteの順番がポイントなのでしょうか?
#3でも書かれていますが、0, NULLのdeleteは問題ありません。
deleteの順番はこの場合はどうでもいいです。
> また、この場合デストラクタA::~A()は実行されるのでしょうか?
されません。
例えば
A *objA = 0;
try {
objA = new A;
} catch (...) {
}
で例外が発生した場合、newの時点で例外発生->catchブロックへジャンプするので
objAに代入されず、objAは0のままです。
このため、objAのデストラクタを呼ぶことはできません。
したがってコンストラクタで例外が発生する場合は、
例外発生前にコンストラクタ内で確保したりソースを解放してからthrowしなければ
そのリソースを解放する手段がなくなります。
No.5
- 回答日時:
少し出遅れましたが、ひとつずつ回答していきます。
> 質問1)newを失敗した場合には、そのポインタに
> 対してdeleteしてはいけないのでしょうか?
原則としては駄目です。
というのも、newに失敗するとstd::bad_alloc例外が創出されるので、そのポインタには何も代入されず、不定状態になります。あらかじめ空ポインタで初期化しておくか、new(std::nothrow)を使って、失敗時に空ポインタが返るようにしておけば問題ありません。
> 質問2)上記3つもエリアの確保のうち、2つめで失敗した場合、1つ目のdeleteをしてやる
> 必要はあるのでしょうか
必要です。
根本的な問題を指摘するなら、コンストラクタの中で複数のnewを行うべきではありません。どうしてもの場合は、std::auto_ptrなど、スマートポインタを使うか、内部的にcatchして辻褄を合わせる(#2の方の方法)しかありません。
long型の配列を三つ用意するのであれば、std::vector<long>を三つ使う方が得策です。
# std::auto_ptrを使えないのは、new[]を使うからですよね?
No.3
- 回答日時:
#1です。
すいません間違ってました。ISOによるとNULLに対するdeleteは無視されるようです。
よってnewが失敗したポインタをdeleteしても問題ないようです。
No.2
- 回答日時:
自分ならこう書きます。
class A {
private:
A();
~A();
long *a,*b,*c;
};
A::A()
: a(0), b(0), c(0)
{
try {
a = new long;
b = new long;
c = new long;
} catch (...) {
delete c;
delete b;
delete a;
throw; //同じ例外をthrow
}
}
A::~A()
{
delete c;
delete b;
delete a;
}
コンストラクタで例外を投げないようにするには、
クラスAは初期化が完全に成功したかを示すフラグメンバ変数を持ち
コンストラクタで例外が起こらなかった場合そのメンバをtrueに設定する。
以降メンバ変数にアクセスする全ての関数の冒頭で
初期化が完全に終わっているかチェックする。
となり、変更箇所が多いためお勧めしません。
この回答への補足
この方法ですと現在のソースの修正がしやすいので、
もう少し教えていただきたいのですが、
たとえば、bのnewでアロケーションを失敗した場合、
Cのポインタは0で初期化された状態で、deleteしても
問題ないのでしょうか?
また、Bのnewで失敗した状態のBにもdeleteを実行することになりますが、問題ないのでしょうか?
deleteの順番がポイントなのでしょうか?
また、この場合デストラクタA::~A()は実行されるのでしょうか?
コンストラクタで例外を投げる方向で設計をしようと思います。よろしくお願いいたします。
No.1
- 回答日時:
>質問1)newを失敗した場合には、そのポインタに対してdeleteしてはいけないのでしょうか?
駄目です。newが失敗したポインタにはNULLが入っています。
>質問2)上記3つもエリアの確保のうち、2つめで失敗した場合、1つ目のdeleteをしてやる必要はあるのでしょうか?
1つ目のdeleteをしてやる必要があります。(解放しないと1つ目のメモリが確保されたままになります。)
std::auto_ptrを使ってはどうでしょうか?
http://www.doumo.jp/postgretips/tips.jsp?tips=78
ありがとうございました。
std::auto_ptrが使えればよかったのですが、
移植性を考えて作る必要があり今回は使用しない
方向で設計をせざるを得なくなりました。
勉強になりました。ありがとうございます。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Java JavaのSingletonパターンのprivateの持つ意味が分かりません。 5 2022/06/12 10:38
- 工学 下記のひろゆきの主張をどうみますか? 9 2023/02/20 14:10
- ヤフオク! Q1)ヤフオクで落札直後、裁判がどうこう言ういきなり出品者の身勝手で落札者に対して失礼な自己満ルール 6 2023/08/12 10:57
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- Visual Basic(VBA) 列 A に同じ日が2つが必要です。 1 2023/03/28 07:25
- 事件・犯罪 刑法についてです 2 2022/06/04 03:11
- 事件・犯罪 刑法についてだれか助けてください。 2 2022/06/05 04:08
- 損害保険 自動車事故の過失割合についての簡易裁判 3 2023/07/30 23:53
- 楽器・演奏 ★ずっと疑問なのですが・・・? 5 2023/02/24 20:18
- 物理学 あのこれは、間違いと 3 2022/11/13 12:22
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
-
なぜ批判コメントをするの?その心理と向き合い方をカウンセラーにきいた!
今や生活に必要不可欠となったインターネット。手軽に情報を得られるだけでなく、ネットを介したコミュニケーションも一般的となった。それと同時に顕在化しているのが、他者に対する辛らつな意見だ。ネットニュース...
-
大麻の使用罪がなかった理由や法改正での変更点、他国との違いを弁護士が解説
ドイツで2024年4月に大麻が合法化され、その2ヶ月後にサッカーEURO2024が行われた。その際、ドイツ警察は大会運営における治安維持の一つの方針として「アルコールを飲んでいるグループと、大麻を吸っているグループ...
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
セグメントエラー
-
ポインタについて
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
ExcelVBAでのkernel32(64bit)
-
popenした子プロセスのプロセス...
-
トリプルポインタが必須!とな...
-
fopne で失敗する原因
-
LPSTR型の初期化について
-
関数ポインタの利点
-
C++で関数ポインタから関数名を...
-
C言語習得のレベル.
-
va_listを使用したfscanf()関数...
-
基本アルゴリズムの『返す』の...
-
nullポインタを逆参照とは?
-
参照送りした構造体のメンバ変...
-
構造体の中の構造体
-
アプリを32bitから64bit移行
-
ポインタを使うことのメリット...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
ExcelVBAでのkernel32(64bit)
-
アプリを32bitから64bit移行
-
参照型で受け取った引数をポイ...
-
fopne で失敗する原因
-
PASCALとFARの意味
-
LPSTR型の初期化について
-
CWnd::EnableWindow()の扱い方
-
ポインタについて
-
プーさんのマウスポインタを教...
-
連結リスト 要素の入れ替え
-
ハンドルはポインタか
-
C++で関数ポインタから関数名を...
-
自作DLLの引数について、ポイン...
-
NULLポインタが0でない処理系と...
-
TCHAR文字列内の検索について
おすすめ情報