え、マジ?すげえ!
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
NGNGプログラム関連の話歓迎。
0002デフォルトの名無しさん
NGNG0003デフォルトの名無しさん
NGNG███▀ █████████ ▄▄▄▄█████▀▀ ████▀▀
███▀ ██ ███▀ ▄███▀ ▀▀▀▀ ███▀
██▀ ▄███▀███▄▄▄███ ▄▄▄█▀
▄███▄▄██▀ █▀ ▀████ ▀██▄
▀▀▀▀███▄ ▄██▀█▄▄ ███
██▀ ███ ██▀ ▀███▄▄ ███
▄████▀▀██ ▄█▀▄▄ ▀█████▄▄ ███
▀█▀▀ █▄▄█▀ ████▄ ▀███▀▀▀ ███
▄ ███ ▀███ ▀▀▀ ███
███ ███ ▀▀ ███
███ ▀ ▀████▄ ▄▄▄▄████
▀ ▀████ ▀█████
▀██▀
0004デフォルトの名無しさん
NGNG0005デフォルトの名無しさん
NGNG0006デフォルトの名無しさん
NGNGC++でのイディオム実装の方法を考えさせてください。
いま俺が興味があるのは、More Effective C++ や Exceptional C++ に
書いてある「リソースの獲得は初期化」ってイディオムです。
CFile file;// not MFC 自作クラスのCFileです
if(file.Load("test.txt") == false) return ERROR;
string str = file.ReadOneLine();// 一行読み込み
みんなこんな感じのコードを書いてると思うんですけど。
「リソースの獲得は初期化」を実装すると、こうなるんじゃないかと。
if(CFile::IsExist("test.txt")) return ERROR;
CFile file("test.txt");
string str = file.ReadOneLine();// 一行読み込み
CFileはファイルを処理するクラスなんですから、CFileのインスタンスが
存在するときには、いつでもそのインスタンスでひとつのファイルを
処理できなくちゃいけないんじゃないかと。逆に言えば、いつでも処理できる
という状態を基準にして、インスタンスを生成しなければならないん
じゃないかと。そのためには、いつもコンストラクタでリソースを確保して、
デストラクタでリソースを解放して。Load,Read,Open,Closeなんて関数は
いっさい作らない(Reloadはアリだと思うけど)。
というのが、「リソースの獲得は初期化」ってイディオムを実装したスタイル
なんじゃないかと思うんですけど、どうでしょう?
「リソースの獲得は初期化」でグーグっても一件しか出てこないのは
どういうわけなんでしょ。みんなこんなことは考えてないんですか。
このイディオムを守ると、リソースリークが激減しそうな予感がするのは
俺だけなんですか。
なんか、何を聞きたいのかさっぱりわからない文章になってますけど、
とりあえずこのイディオムの実装の仕方とかを考えてる人と話したいんです…。
0007デフォルトの名無しさん
NGNG0008デフォルトの名無しさん
NGNG駄スレにレスるのもなんだが、オレなら例外にするかな。
try {
CFile file("foo.txt");
// 処理……
}
catch (FileNotFoundException& e) {
}
catch (FileIOException& e) {
}
File not found を例外と考えるかどうかは意見の分かれるところだが。
0009デフォルトの名無しさん
NGNG「駄スレを速攻で終了させる方法を話し合うスレ part 1」
となりました。
0011デフォルトの名無しさん
NGNG漏れにも優良駄スレを作るコツを教えてくれ!
漏れ的に考えると
優良駄スレ=厨房隔離スレ
だろうか。
0012デフォルトの名無しさん
NGNG>駄スレにレスるのもなんだが
あー、やっぱC++相談室あたりのちゃんとしたスレで聞いた方が
良かったんですかね…。マルチポストって言われないように、
何を聞きたいのかをちゃんとまとめ直して投稿します。
>オレなら例外にするかな。
そうですね。CFileのコンストラクタは、どっちみち例外を
投げるしかないですから。関数の呼び出しの浅い部分では
IsExistでチェックしておいて、深い部分では例外に任せるのが
いいかもしれません。
0013デフォルトの名無しさん
NGNG確かに、C++相談室の方が良いと思われ。
>>11
長年の経験によると、優良駄スレは
・1に長文が書かれている。・その内容が、ツッコミ所満載。
・1が厨房。・1が常駐。・1が無知。・1が知ったかぶる。
・2ゲットされている。・ネタに付き合ってくれる住人が4人以上居る。
うえの条件を6つ以上満たしているのが、優良駄スレだと思われる。
0014デフォルトの名無しさん
NGNG0015デフォルトの名無しさん
NGNGここでレスするときは、ちゃんと最初に上記のフレーズを書き込むこと。
00161
NGNG0017デフォルトの名無しさん
NGNGズゲエ ズゲエヨ オマエ
0018デフォルトの名無しさん
NGNG場合優良スレになることがある。
そして俺も読んでこっそり勉強してたりする。いや、立てたことはないけどね。
0019デフォルトの名無しさん
NGNG0020デフォルトの名無しさん
NGNGある。でも最近は無い。
0021デフォルトの名無しさん
NGNGどれよ?
0022デフォルトの名無しさん
NGNGコンストラクタの例外投げって、ありか?
おれとしては、あってはならないもののような気がする・・・
0023デフォルトの名無しさん
NGNGぉぃぉぃ
0024デフォルトの名無しさん
NGNGありです
0025デフォルトの名無しさん
NGNGデストラクタの勘違い?
0026
NGNG5名以上7名人お聞かせください。(18歳以下タレント、東京以
外のタレント、アナは除く)
その中でご相談可能な名前があった場合のみお返事いたします。
場所は本州の県庁所在地から選んでください。
秘密を守るため即決で受け付けますので、問い合わせ後12時間
後以降18時間以内に返信チェック願います。
メールは下記アドレスあて女優名(5名以上)、希望都市、年令
をお送りください。返信ボタンは使わないでください。
記載、人数が欠けていた場合返信できない場合があります。
[email protected]
0027.
NGNG0028デフォルトの名無しさん
NGNGコンストラクタでもデストラクタでも例外投げって、別にかまわんでしょ?
0029デフォルトの名無しさん
NGNG003030げっと-
NGNG███▀ █████████ ▄▄▄▄█████▀▀ ████▀▀
███▀ ██ ███▀ ▄███▀ ▀▀▀▀ ███▀
██▀ ▄███▀███▄▄▄███ ▄▄▄█▀
▄███▄▄██▀ █▀ ▀████ ▀██▄
▀▀▀▀███▄ ▄██▀█▄▄ ███
██▀ ███ ██▀ ▀███▄▄ ███
▄████▀▀██ ▄█▀▄▄ ▀█████▄▄ ███
▀█▀▀ █▄▄█▀ ████▄ ▀███▀▀▀ ███
▄ ███ ▀███ ▀▀▀ ███
███ ███ ▀▀ ███
███ ▀ ▀████▄ ▄▄▄▄████
▀ ▀████ ▀█████
▀██▀
次は300だね?
003130げっと-
NGNG0032デフォルトの名無しさん
NGNG↓こういうコードでコンストラクタが例外投げた場合の話よ?
Hoge *hoge = new Hoge();
0033デフォルトの名無しさん
NGNGメンバ変数という概念がなくて、インスタンスは全てシングルトンで
必要になったその時に作る、必要なくなったら破棄、
こういう言語があったらどうだろう?難しいかな?
でも、どうもCFile::IsExistの存在に違和感を感じるかな。
そこまでやるなら、使用したい時に CFile file("test.txt") と
インスタンスを作る方がスマートのような気がする。
まあコンストラクタん中にIsExistを埋め込めばより良いだろうけど。
003433
NGNGならない。
0036デフォルトの名無しさん
NGNG試したら本当だった。何時から仕様になったんだ?
0037デフォルトの名無しさん
NGNG0038デフォルトの名無しさん
NGNGあ、本当だったってのはメモリリークを起こさなかったってことね。
下記コードで実行中のメモリ使用量変わらず (throw を抜くとすごい
勢いでメモリを消費する)。
_______________________________________________
// Cobalt Linux, gcc-c++-2.95.3-1c1r4, glibc-2.1.3-23
class A{
char buffer[1024 * 1024];
public:
A(){
throw 100;
}
};
int main(void){
while(1){
try{
A *a = new A();
} catch(int x){/* */}
}
return 0;
}
ちなみにメモリリークすると覚えたのは数年前の Turbo C++ 4 だったか
Visual C++ 4.0。
0039デフォルトの名無しさん
NGNGそれは例外 以前の問題でしょ。
0040デフォルトの名無しさん
NGNGdeleteしてないから当然?
0041デフォルトの名無しさん
NGNGコンストラクタ内で例外を起こすと
インスタンスは生成されないのか?って実験だから
いいと思うけど。
0043デフォルトの名無しさん
NGNGthrowする前にbufferにアクセスした場合どうなるの?
memset(buffer,sizeof(buffer));
throw 100;
とか。
一度スタックに取られる?
004443
NGNGんなわけないか・・
0045デフォルトの名無しさん
NGNGコンストラクタの時点でメモリは確保されているが、
例外を送出すると自動で解放されるようになっている。
operator new(size_t s)
{
void* p = NULL;
try {
p = malloc(size);
if (p == NULL)
throw std::bad_alloc();
ctor(p);
}
catch (...) {
free(p);
throw;
}
}
004643
NGNGああ、そういうわけですか。
判りやすい説明どうもです。
コンストラクタで例外出さないってのは常識だと思ってたんだがな。
今はそうなってるんだ。俺の覚えている範囲では、C++ がまだ ANSI
ドラフトだった頃の実装は軒並みリークしてたな。
0048デフォルトの名無しさん
NGNG> コンストラクタで例外出さないってのは常識だと思ってたんだがな。
意味を理解しないで憶えてるから、「思ってたんだがな。」なんて
情けないことを言う羽目になる。
0049デフォルトの名無しさん
NGNG0050デフォルトの名無しさん
NGNGハハハ、まるでnewの実装まで知らなければ
例外を使ってはいけないような口ぶりですな。
それは違うのでは?
0051デフォルトの名無しさん
NGNGそれリダイレクト先間違ってる。
>>48じゃなく>>47がふさわしい。
0052デフォルトの名無しさん
NGNGnewの実装を知らなければ、コンストラクタから安心して例外を出せないと思うが。
リークしないのは仕様だし、リークする処理系はバグ持ちと言うことなんだから。
勝手な思いこみでリークするとか言ってるんか、使っちゃだめだろ。
0053デフォルトの名無しさん
NGNGhttp://www.microsoft.com/japan/developer/library/vccore/_core_exceptions.3a_.exceptions_in_constructors.htm
http://www.cmagazine.jp/src/kinjite/cpp/exception.html
リークするしないは処理系によると思うので
どちらも正しいと言えるのでは?
0054デフォルトの名無しさん
NGNGしったか莫迦 ハケーン!
おまえ ANSI の仕様と処理系の仕様を理解しないで覚えてるだろ。
ANSI のどこにそんな「仕様」があるんだ?
0055デフォルトの名無しさん
NGNGそこで言うリークは、クラス内でnewしたオブジェクトの話であって、また別の次元の話。
newされたオブジェクトがコンストラクタ内で例外を送出したときは、
そのオブジェクトに割り当てられたメモリは解放されます。
0056デフォルトの名無しさん
NGNG> 余分な引数を付けずに operator new を使用し、/GX、/EHs、または /EHa オプションで
> コンパイルすると、コンストラクタが例外をスローしたときに operator delete を呼び
> 出すコードが生成されます。
なので VC で delete が呼び出されるかどうかはコンパイルオプションに依存。
つまりコンストラクタの例外でメモリ開放を期待する設計は処理系/環境依存の
プログラムになる。
ちなみにこんな記述もある。
> 仮引数付きの new 演算子、つまり割り当てサイズ以外の引数を伴う形式の
> new 演算子を使用すると、コンストラクタが例外をスローしたときに、
> 仮引数付きの delete 演算子が呼び出されません。
0058デフォルトの名無しさん
NGNG上 URL の第二パラグラフをよく読め。オブジェクト自身に割り当てられたメモリの話だ。
0059デフォルトの名無しさん
NGNGコンストラクタ内で例外が発生した場合:
1. そのオブジェクト自身の領域が解放されるのは (言語仕様 | 処理系依存)
2. (その未完成オブジェクトに対して) デストラクタが呼び出されるのは (言語使用 | 処理系依存)
※2 はコンストラクタ内で別オブジェクトを作成してメンバに格納し、デストラクタで
開放するクラスを想定している。デストラクタが呼び出されないと例外発生前に確保
したオブジェクトが開放されないという意味。
>>53, >>56 を見る限りどちらも処理系依存っぽい。
0060デフォルトの名無しさん
NGNG>If the object or array was allocated in a newexpression and the newexpression does not contain a newplacement, the deallocation function (3.7.3.2, 12.5) is called to free the storage occupied by the object;
placement-newで確保されてないオブジェクトは自動で解放されるとある。
>>56は環境依存じゃなくてVC依存の問題。
0061デフォルトの名無しさん
NGNG2 仕様違反
class A{
string s;
char* p;
public:
A() {
p = new char[256];
s = "string";
throw;
}
~A()
{
delete[]p;
}
};
A* pa = new A();
すべての処理は正しく終了する物とする。
この場合、A::sはオブジェクトの作成に成功しているので、
・コンストラクタで例外が呼ばれてもA::sのデストラクタは呼ばれる。
・例外が送出されているので、paは解放される。
・デストラクタが呼び出されていないので、A::pはリークする。
0062デフォルトの名無しさん
NGNG> オブジェクトか配列がnewexpressionの中で割り付けられ、newexpressionが
> newplacementを含んでいない場合、deallocation関数(3.7.3.2、12.5)は
> オブジェクトによって占められた記憶装置を解放するために呼ばれます;
newplacement って何のことだろう? これはどこからの引用?
0063デフォルトの名無しさん
NGNGplacement-newと呼ばれている物。
たとえば、
char buf[sizeof(Obj)];
new(buf) Obj();
こんな感じで好きなようにオブジェクトの生成位置をコントロールできる物。
引用源はISOの規格書
0064デフォルトの名無しさん
NGNGうはっ、しばらく触らんうちに C++ が進化しとる (;´Д`)
今まで出た話としては:
・言語規格としてオブジェクト自身の領域は解放されなければいけないが、
(数年前クラスの) 古いコンパイラの幾つかは未対応のものもある。
・コンストラクタ内で例外が発生した場合、デストラクタが呼び出されるか
(呼び出されるようにコンパイルできるか) は処理系依存。
ってことですか。
0065デフォルトの名無しさん
NGNG0066デフォルトの名無しさん
NGNGお馬鹿お馬鹿お馬鹿〜、お馬鹿〜に〜なる〜のさ〜
0067デフォルトの名無しさん
NGNG> (呼び出されるようにコンパイルできるか) は処理系依存。
だから、デストラクタが呼び出されるのは仕様違反だって言ってるんだよ。
デストラクタが呼び出される要件はただ一つ。
オブジェクトが正しく生成されていると言うことだけ。
コンストラクタが例外を出したらオブジェクトは無かったことになるので
呼び出されるはずがない。
placement-newでメモリが解放されないのは、
newがメモリを確保するのではなくすでにメモリの存在している領域にオブジェクトを作るから。
オーバーロードで定義された引数付きnew
ex. void* operator new(size_t s, int)
で割り当てられたオブジェクト例外を出した場合は、対応する引数付きdelete
ex. void operator delete(void* p, int)
が呼び出される。
また、この引数付きoperator deleteは能動的に呼び出すことは出来ない。
0068デフォルトの名無しさん
NGNGわりい。処理系依存ってのはコンパイラがオプションによって
スイッチする機能を持ってるかどうかという意味。
0069デフォルトの名無しさん
NGNG・コンストラクタ内で例外が発生した場合、未完全なオブジェクトに対して
デストラクタを呼び出すようなコンパイルオプションを持ったコンパイラ
もある。
0070デフォルトの名無しさん
NGNGそんなことを言い出したら、すべてが実装依存って事になるぞ。
0071デフォルトの名無しさん
NGNGそのオブジェクトが未完成のまま放置されたりはせず、必ず解放されると
受け取れるんだけど、この部分で処理系での違いはないと認識して良いの?
0072デフォルトの名無しさん
NGNG0073デフォルトの名無しさん
NGNGnewした親objectの中でさらにnewした子objectがあったら、
コンストラクタ内で子をnewで生成した後に親objectで例外送出したら、
子objectは開放されないということですか?
007448
NGNGコンストラクタで例外を送出すれば、デストラクタは呼ばれず、メモリリークの元になる。
コンパイラのオプションだ何だと、まだバカが居るが、こんなの常識だよ。
0075デフォルトの名無しさん
NGNGそのとおり
しかし、例外が子オブジェクトのコンストラクタから送出されたのなら、リークは起こらない。
また、このためのstd::auto_ptrだったり、他のスマートポインタだったりが用意されている(言い過ぎかも
007648
NGNG子オブジェクトのデストラクタは呼ばれないぞ。
007748
NGNGデストラクタの話と混同するな。
0078デフォルトの名無しさん
NGNGは?関係ないじゃん。
class A{
public A() { throw; }
};
class B
{
A* a;
public
B() : a(new A) { }
}
B* b = new B();
この場合は、B::AもB自身もリークしないと言うだけ。
007948
NGNGつき合うのに疲れた。
Aについて、自分でよく考えろ。
0080デフォルトの名無しさん
NGNG偉そうな割に頭悪いな。
#include <iostream>
class A
{
public:
A() { throw 0; }
void* operator new(size_t s)
{
std::cout << "A::new" << std::endl;
return ::operator new(s);
}
void operator delete(void* p)
{
std::cout << "A::delete" << std::endl;
::operator delete(p);
}
};
class B
{
A* a;
public:
B() : a(new A()) { }
void* operator new(size_t s)
{
std::cout << "B::new" << std::endl;
return ::operator new(s);
}
void operator delete(void* p)
{
std::cout << "B::delete" << std::endl;
::operator delete(p);
}
};
main()
{
try {
B* b = new B();
}
catch (...) {
}
}
実行結果
B::new
A::new
A::delete
B::delete
0081デフォルトの名無しさん
NGNG>例外が子オブジェクトのコンストラクタから送出されたのなら、リークは起こらない。
子オブジェクトの生成に失敗したのだから、
自動でメモリは回収されてデストラクタ云々は全く無関係の話。
子オブジェクトからの例外を適切に処理出来なかったんだから、
親オブジェクトも生成失敗となり、こちらも回収されて一件落着。
0082デフォルトの名無しさん
NGNG0084デフォルトの名無しさん
NGNG>>73をまた読み直してしまう罠。
>>48、あんた質問を読み違えて勘違いしてるんじゃない?
0085デフォルトの名無しさん
NGNG0086デフォルトの名無しさん
NGNG008748
NGNG自分で考えろと言っただろ。
説明はこれで最後だぞ、二度とないからな。
これだけ説明してわからんバカに、これ以上つき合ってられん。
親はダメで、子は大丈夫なんて、ナンセンスだろ。
オブジェクトは、親用とか子用ってのがあるのか?
子のコンストラクタでnew使ってたら、子のデストラクタが必要だろ。
008848
NGNGもう2度と、お前の相手はしないからな。
0089デフォルトの名無しさん
NGNG0090デフォルトの名無しさん
NGNG子のデストラクタが必要だとしても、子のコンストラクタ内でnewに
失敗したら呼び出されないのでは・・・・・・
0091デフォルトの名無しさん
NGNG>自作自演やめれ。ほとんどの人間は、もう理解できた。
>自分がバカと理解してないバカはやっかいだ・・・
0092デフォルトの名無しさん
NGNG48は80のソースの読み方を知らないか、
実行結果が理解できないのです。
0093デフォルトの名無しさん
NGNG語の悪影響でしょうかねぇ。
0094デフォルトの名無しさん
NGNG理解できました!!!
>>90 でも、1つ目newが成功して、2つ目のnewが失敗しての場合、必要だと思います。
ていうか、常にデストラクタは必要だと思います!!
0095デフォルトの名無しさん
NGNGそりゃそうだ罠。
0096デフォルトの名無しさん
NGNGガメコレってあんた・・・・ワラタよ
0097デフォルトの名無しさん
NGNG別にデストラクタでなくてもいい。
確保した領域を確実に開放出来る機構を設ければいいだけ。
コンストラクタの中で確保したのならば、
コンストラクタの中のcatch{}の中で解放してやればいい。
0098デフォルトの名無しさん
NGNG一つ目のnewが成功して、二つ目のnewが失敗した時に例外が
投げられたら、デストラクタは呼び出されません。よって
>>97さんのような機構は不可欠。
0099デフォルトの名無しさん
NGNG込んだ時刻や文体から、バレバレですが。初心者の方が誤解されると困るので、中
身のないプライドは捨てて、少し勉強をやり直すことをお勧めします。それでも理
解できないのなら、可哀想ですがプログラマになるのはあきらめた方が、貴方のた
めにもよろしいと思います。
>>97
コンストラクタでcatchするのは、誰も問題にしてませんよ。何度も貴方が書いて
きたソースのように、コンストラクタから外へthrowするのが問題なのです。
0100デフォルトの名無しさん
NGNG俺も試してみたがやはりリークは起こらないが。
いったい何が駄目なん?
#include <crtdbg.h>
class a
{
int b[0xffff];
public :
a(){throw 0;};
};
int main(int argc, char* argv[])
{
try{
a* pa = new a;
delete pa;
}
catch(...){
}
_CrtDumpMemoryLeaks();
return 0;
}
0101デフォルトの名無しさん
NGNG0102デフォルトの名無しさん
NGNG#include <iostream>
using namespace std;
class Test {
int *i;
void except_func() throw(int) { throw 0; }
public:
Test() throw(int) { i = new int; except_func(); }
~Test() { delete i; }
};
int main()
{
try {
Test t;
}
catch (int) {
cout << "exception thrown." << endl;
}
}
0103デフォルトの名無しさん
NGNG低 学 歴 が 混 ざ っ て い る よ う で す
0104デフォルトの名無しさん
NGNGコンストラクタで、10個の異なるオブジェクトを、順番にnewでつくる場合の、エラー処理を記述してみればわかりやすいと思う。
0105デフォルトの名無しさん
NGNGつまり、コンストラクタ内で、例外を起こす前に確保したオブジェクトは、
解放する手段がないために、メモリリークを起こします。
(コンストラクタ内で例外をcatchしてオブジェクトを解放してやれば済むけど)
これで分からない初心者はコンストラクタで例外を起こさなければよし!
0106デフォルトの名無しさん
NGNGホッ、よかった。合ってたみたい。サンクス。
0107デフォルトの名無しさん
NGNG何当たり前な事言ってるの?
生成に「成功」したオブジェクトがリークするというのは>>75の時点でガイシュツでしょ
子オブジェクトも生成に失敗した場合は、リークが起こらないって話じゃなかったの?
で、成功したオブジェクトがある場合、リークして困るなら
生ポインタじゃなくてauto_ptrにすれば成功した分も自動で解放される、と。
0108デフォルトの名無しさん
NGNGそう、それでいいよ。
で、君は何が不満なの?
その解で満場一致じゃん。
0109デフォルトの名無しさん
NGNG0110デフォルトの名無しさん
NGNG48だと思ってたんだが、冷静に見ると口調が丁寧だ。
スマソ
0111デフォルトの名無しさん
NGNG■ このスレッドは過去ログ倉庫に格納されています