スレッド: [cppll:9323] インスタンスを生成して返す関数内部で例外が発生した時のルール

スレッド

[cppll:9323] インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | ▲ / | ]
Subject:
[cppll:9323] インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Takefumi Nakayama <naka@...>
Date:
Thu, 07 Aug 2003 15:37:24 +0900
X-Mailer:
Becky! ver. 2.00.08
Message-Id:
<20030807152156.7946.NAKA‐at‐reedrex.co.jp>
こんにちは。中山です。
#またしてもしょーもない質問かもしれませんが、
#一応「2929」あたりから始まるスレを見ましたが、、、これは例外に関する話題でした。
#これも相当参考になりました。

下記のように、インスタンスを生成して返す関数があります。

CHoge *CreateNewInstance( int type );

この関数内部で例外が発生した場合、、
もしくは、引数間違いとかがあって、インスタンスを返したくない場合、
下記の2通り思いつくのですが、どちらが良いでしょう?
・NULLを返す。
・例外を発生させる。
※場合によってはNullObjectを返すこともあると思いますが。

今、私は下記のように「NULLを返す」ようにしています。

------------------------------------------------------------------------------------
CHoge *CreateNewInstance( int type )
{
   CHoge *ret = NULL;

   try{
       auto_ptr<CHoge> temp( new CHoge );

       if( type > TYPE_MAX ) throw CException( E_TYPE_IS_INVALID );

       //データセットとか何かの処理(例外が発生するかも)

       //全ての処理に成功したら、インスタンスを返す。
       ret = temp.release();
   }catch( CException &e ){
       //何かしらの例外が発生したら
       //「auto_ptr<CHoge> temp」のスコープが外れて開放される。

       //ここで再throwするべき?
       // throw;
   }catch( ... ){
       //何かしらの例外が発生したら
      //「auto_ptr<CHoge> temp」のスコープが外れて開放される。
   }

   return ret;
}
------------------------------------------------------------------------------------

好み、ポリシーの問題になりそうですが、、、どっちが主流かな?と皆さんの意見を聞かせてください。
他の会社に行った時に通用するように(笑)
それから、今の社内のコードのルール化を進めるための参考とさせていただくために。。
よろしくお願いします。

<余談>
 さて、またしても、私のコードを見て同じプロジェクトに入りたくなくなった方の挙手願います(笑)
 というか、今まで自分が書いたコードが、他者にどう見えるのか意識したことがなかったのですが、
 最近、自分のコードが読みやすいのか?一般的なやり方なのか?が気になり始めました。
 プロ集団が集まるこのMLリストに今後も自分のコードを晒させていただきたいと思いますが、
 迷惑じゃないでしょうか?
</余談>


"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~
中山 剛史 <naka@...>
"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~

[cppll:9325] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9325] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
DENCHU <cppll@...>
Date:
Thu, 07 Aug 2003 16:02:50 +0900
X-Mailer:
Datula version 1.52.01 for Windows
Message-Id:
<E19kenS-0001Dx-00‐at‐deedlian.denchu.jp>
In-Reply-To:
9323
References:
9323
Takefumi Nakayamaさんの<20030807152156.7946.NAKA@reedrex.co.jp>から
>好み、ポリシーの問題になりそうですが、、、どっちが主流かな?と皆さんの意見を聞かせ
>てください。

 私は NULL を返すのがほとんどですね。どちらかっていうと C のお仕
事が多いので、癖になっています。

 ただ、最近思うのが多重に呼び出される関数の内部でエラーが起きた
とき、NULL を返すとなると、ちとめんどい事ですね。

 そういう場合は例外の方が楽なんでしょうね。

--
電柱一家
mailto:cppll@...
http://denchu.jp/

[cppll:9329] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9329] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Takefumi Nakayama <naka@...>
Date:
Thu, 07 Aug 2003 16:34:22 +0900
X-Mailer:
Becky! ver. 2.00.08
Message-Id:
<20030807163124.794E.NAKA‐at‐reedrex.co.jp>
In-Reply-To:
9325
References:
9323 9325
こんにちは。中山です。

>  ただ、最近思うのが多重に呼び出される関数の内部でエラーが起きた
> とき、NULL を返すとなると、ちとめんどい事ですね。

そうなんですよね。
結局
if( (pHoge = CreateNewInstance( type )) == NULL )
みたいなことやらなあかんのか?
って話になると、例外の方が楽には楽なんですが、
「例外はgotoかよ?」みたいな話題が以前の「2929」あたりのスレであったので、、
いや、中身はまだきちんと読んでないんですけど(^^;)

他の方の意見も多く聞かせていただきたいです。

"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~
中山 剛史 <naka@...>
"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~

[cppll:9330] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9330] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Osamu Shigematsu <m5issige@...>
Date:
Thu, 07 Aug 2003 16:44:39 +0900
X-Mailer:
Becky! ver. 2.06.02
Message-Id:
<20030807163331.E598.M5ISSIGE‐at‐mr.hitachi-medical.co.jp>
In-Reply-To:
9325
References:
9323 9325
重松です。こんにちは。

>  そういう場合は例外の方が楽なんでしょうね。

理由を返せるので、例外のほうが便利な気もします。
というわけで、例外に一票。

で、環境に依存した話になるのかもしれませんが、
例外にはどの程度コストがかかるものなのでしょうか。
投げた場合も、平穏だった場合も。

http://www.microsoft.com/japan/developer/library/vccore/_core_exception_handling_overhead.htm

辺りを見ると、スイッチ (オプション) でコストが変わるようにも読めます。
# 参照せよとある本はあいにく持ってません。。。

--
Osamu Shigematsu <m5issige@...>

[cppll:9331] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9331] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
FUKUDA Fumiki <fukuda.fm@...>
Date:
Thu, 07 Aug 2003 17:04:19 +0900
X-Mailer:
WeMail32[1.42] ID:NTES00
Message-Id:
<200308070811.h778BWQ15266‐at‐mailsv3.nec.co.jp>
In-Reply-To:
9330
επιστημηです。

--- "[cppll:9330] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール" / Osamu Shigematsu ---

>例外にはどの程度コストがかかるものなのでしょうか。
>投げた場合も、平穏だった場合も。

例外飛んだときにたどり着くトコをスタック上に載せて
おくことになろうかと思います。だから例外が飛ぼうが
飛ぶまいが、この刻印を打つのにコストかかりそ。

-----:-----:-----:-----:-----:-----:-----:-----:-----:-----
FUKUDA (episteme) Fumiki -- magical, but never a magic...

[cppll:9334] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9334] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Osamu Shigematsu <m5issige@...>
Date:
Thu, 07 Aug 2003 17:32:22 +0900
X-Mailer:
Becky! ver. 2.06.02
Message-Id:
<20030807172649.E5A2.M5ISSIGE‐at‐mr.hitachi-medical.co.jp>
In-Reply-To:
9331
References:
9330 9331
重松です。こんにちは。

> 例外飛んだときにたどり着くトコをスタック上に載せて
> おくことになろうかと思います。だから例外が飛ぼうが
> 飛ぶまいが、この刻印を打つのにコストかかりそ。

そんな気がするんですが、以前どこかで、多分、CodeWarrior 関連だったと
思うのですが、例外が発生しなれば、まったくコストはかからない、
というようなのを呼んだ記憶があります。
# Google 先生に聞いてみてますが、キーワードが悪いのか、
# なかなかヒットしません...。

確かに、めったに発生しないから例外なわけで
それでコストがかかるのはかなりばかばかしい話だと思って、
妙に納得した気がするのですが、わざわざそれが語られるということは、
そうでない環境もたくさんあったりして、コストも案外かかるんだと、
それはそれでやっぱり NULL かしらと思ったりしました。

--
Osamu Shigematsu <m5issige@...>

[cppll:9338] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9338] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Akira Higuchi <a-higuti@...>
Date:
Thu, 7 Aug 2003 18:59:04 +0900
X-Mailer:
Sylpheed version 0.6.5 (GTK+ 1.2.10; i586-redhat-linux)
Message-Id:
<20030807095204.IWZL28295.mpb3.plala.or.jp@tp>
In-Reply-To:
9334
References:
9330 9331 9334
樋口です。

On Thu, 07 Aug 2003 17:32:22 +0900
Osamu Shigematsu <m5issige@...> wrote:

> > 例外飛んだときにたどり着くトコをスタック上に載せて
> > おくことになろうかと思います。だから例外が飛ぼうが
> > 飛ぶまいが、この刻印を打つのにコストかかりそ。
>
> そんな気がするんですが、以前どこかで、多分、CodeWarrior 関連だったと
> 思うのですが、例外が発生しなれば、まったくコストはかからない、
> というようなのを呼んだ記憶があります。

VC++の場合、例外が通り抜けた場合に後始末が必要なフレームには刻印を打つ
るコードが常に生成されるようです。よって例外が飛ばなくても実行時コスト
が少しかかります。

GCCの場合、それらしきコードは一切生成されず、そのかわり謎の構造のテー
ブルが生成されます。例外が飛ばない場合には、実行時のコストはかかりま
せん。

吐いたコードを読む限りではこのような感じなのですが、どこかでVC++でも
事実上コストがかからないと書いてあったような気がします。

例外が飛んだ場合のコストは実験してみないとわかりませんが、やはりトレー
ドオフがあるのではないでしょうか。

[cppll:9339] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9339] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Osamu Shigematsu <m5issige@...>
Date:
Thu, 07 Aug 2003 20:12:21 +0900
X-Mailer:
Becky! ver. 2.06.02
Message-Id:
<20030807200832.E5AE.M5ISSIGE‐at‐mr.hitachi-medical.co.jp>
In-Reply-To:
9338
References:
9334 9338
重松です。こんにちは。

> VC++の場合、例外が通り抜けた場合に後始末が必要なフレームには刻印を打つ
> るコードが常に生成されるようです。よって例外が飛ばなくても実行時コスト
> が少しかかります。
>
> GCCの場合、それらしきコードは一切生成されず、そのかわり謎の構造のテー
> ブルが生成されます。例外が飛ばない場合には、実行時のコストはかかりま
> せん。
>
> 吐いたコードを読む限りではこのような感じなのですが、どこかでVC++でも
> 事実上コストがかからないと書いてあったような気がします。

GCC の場合には、逆説的にいえば、そのテーブルがロードされるコストが
かかってしまいますね。そして、それは例外発生時に払われるので、
VC 方式に比べて、例外時のコストが大きいと、理解してよいでしょうか?

> 例外が飛んだ場合のコストは実験してみないとわかりませんが、やはりトレー
> ドオフがあるのではないでしょうか。

基本的には、トレードオフにはあると思いますが、例外の発生頻度が
少ない場合 (基本的は、例外が発生することはまれなはず) に、
有利なものの法が優れている気がします。

--
Osamu Shigematsu <m5issige@...>

[cppll:9347] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9347] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
KOIE Hidetaka <hide@...>
Date:
Thu, 07 Aug 2003 22:33:08 +0900 (JST)
X-Mailer:
Mew version 4.0.58 on Emacs 21.1 / Mule 5.0 (SAKAKI)
Message-Id:
<20030807.223308.45893332.hide‐at‐koie.org>
In-Reply-To:
9339
References:
9334 9338 9339
Message-Id: <20030807200832.E5AE.M5ISSIGE@mr.hitachi-medical.co.jp>
 Date:       Thu, 07 Aug 2003 20:12:21 +0900
 From:       Osamu Shigematsu <m5issige@...>
 Subject:    [cppll:9339] Re: インスタンスを生成して返す関数内部で例..

 | 重松です。こんにちは。
 |
 | > VC++の場合、例外が通り抜けた場合に後始末が必要なフレームには刻印を打つ
 | > るコードが常に生成されるようです。よって例外が飛ばなくても実行時コスト
 | > が少しかかります。
 | >
 | > GCCの場合、それらしきコードは一切生成されず、そのかわり謎の構造のテー
 | > ブルが生成されます。例外が飛ばない場合には、実行時のコストはかかりま
 | > せん。
 | >
 | > 吐いたコードを読む限りではこのような感じなのですが、どこかでVC++でも
 | > 事実上コストがかからないと書いてあったような気がします。
 |
 | GCC の場合には、逆説的にいえば、そのテーブルがロードされるコストが
 | かかってしまいますね。そして、それは例外発生時に払われるので、
 | VC 方式に比べて、例外時のコストが大きいと、理解してよいでしょうか?

例外テーブルの大きさがどのくらいになるか調べたことはないのですが
ロードするコストよりも例外発生時のテーブルを検索するコストに
支配されるとおもいます。
検索コストは関数の数をNとした場合にテーブルを二分探索するとO(log N)。

昔gccに例外処理が入りたてのころコードを読んだ記憶だと、
throwすると例外が発生したプログラムカウンタから
そのスタックフレームのunwind前にすべき処理をみつけだして実行、
スタックをunwindして例外がcatchされるかtopにぶるかるまでグルグルまわす、
だったとおもいます。

 |
 | > 例外が飛んだ場合のコストは実験してみないとわかりませんが、やはりトレー
 | > ドオフがあるのではないでしょうか。
 |
 | 基本的には、トレードオフにはあると思いますが、例外の発生頻度が
 | 少ない場合 (基本的は、例外が発生することはまれなはず) に、
 | 有利なものの法が優れている気がします。
 |
 | --
 | Osamu Shigematsu <m5issige@...>
 |
 |
 | --[PR]------------------------------------------------------------------
 | 【 FreeML ユーザー登録してますか?】
 |   ・メールアドレスとパスワードのカンタン登録!
 |   ・ニックネームもつけられるし、WEBメールも使える!
 |   ・MLだってカンタンに作れちゃう!
 | ▼ いますぐ登録! => http://click.freeml.com/ad.php?id=934686
 | ------------------------------------------------------------------[PR]--
 | <GMO GROUP> Global Media Online  www.gmo.jp
 |

[cppll:9348] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9348] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Akira Higuchi <a-higuti@...>
Date:
Fri, 8 Aug 2003 00:27:13 +0900
X-Mailer:
Sylpheed version 0.6.5 (GTK+ 1.2.10; i586-redhat-linux)
Message-Id:
<20030807152013.JUCJ20517.mps4.plala.or.jp@tp>
In-Reply-To:
9347
References:
9334 9338 9339 9347
樋口です。

On Thu, 07 Aug 2003 22:33:08 +0900 (JST)
KOIE Hidetaka (鯉江英隆) <hide@...> wrote:

>   | GCC の場合には、逆説的にいえば、そのテーブルがロードされるコストが
>   | かかってしまいますね。そして、それは例外発生時に払われるので、
>   | VC 方式に比べて、例外時のコストが大きいと、理解してよいでしょうか?
>
> 例外テーブルの大きさがどのくらいになるか調べたことはないのですが
> ロードするコストよりも例外発生時のテーブルを検索するコストに
> 支配されるとおもいます。
> 検索コストは関数の数をNとした場合にテーブルを二分探索するとO(log N)。

簡単なコードを書いてVC++とgccで計測してみました。
テストの内容は、ほとんど何もしない関数を1億回呼び出すだけです。
「例外を投げる」ほうは、その関数の中で例外を投げ、ループの内側で
catchします。どちらもほぼ限界まで最適化をかけてあります。
ループのアンロールはしていません。

VC++
例外投げない   0.44秒
例外投げる   212.05秒

gcc
例外投げない   0.35秒
例外投げる   966.55秒

どちらのほうが嬉しいかは微妙なところです。

しかし例外処理がこれほど遅いものだとは知りませんでした。

[cppll:9349] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9349] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Shu KONNO <owa@...>
Date:
Fri, 8 Aug 2003 00:49:40 +0900
X-Mailer:
Sylpheed version 0.8.5 (GTK+ 1.2.10; i386-vine-linux)
Message-Id:
<200308071549.h77Fnegk091901‐at‐bg.wakwak.com>
In-Reply-To:
9348
References:
9334 9338 9339 9347 9348
今野です

On Fri, 8 Aug 2003 00:27:13 +0900
Akira Higuchi <a-higuti@...> wrote:
> 簡単なコードを書いてVC++とgccで計測してみました。

ぜひ、コードを載せてください。

--
Shu KONNO
http://owa.as.wakwak.ne.jp/zope

[cppll:9350] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9350] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Akira Higuchi <a-higuti@...>
Date:
Fri, 8 Aug 2003 09:03:00 +0900
X-Mailer:
Sylpheed version 0.6.5 (GTK+ 1.2.10; i586-redhat-linux)
Message-Id:
<20030807235601.HSOZ10930.mps6.plala.or.jp@tp>
In-Reply-To:
9349
References:
9334 9338 9339 9347 9348 9349
樋口です。

On Fri, 8 Aug 2003 00:49:40 +0900
Shu KONNO <owa@...> wrote:

> On Fri, 8 Aug 2003 00:27:13 +0900
> Akira Higuchi <a-higuti@...> wrote:
> > 簡単なコードを書いてVC++とgccで計測してみました。
>
> ぜひ、コードを載せてください。

------- exptiming.cpp --------------------------------------

#include <time.h>
#include <stdio.h>
#include "exptiming.h"

int foo_destr_count = 0;

struct foo {
 foo(int x) : v(x) { }
 ~foo() { foo_destr_count += v; }
 int v;
};

void exptest1()
{
 foo f(1);
 unknown_func1();
}

void exptest2()
{
 foo f(1);
 unknown_func2();
}

struct timing {
 timing() : start_cl(::clock()) { }
 ~timing() {
   printf("%f\n", double(::clock() - start_cl) / double(CLOCKS_PER_SEC));
 }
 clock_t start_cl;
};

int main()
{
 const size_t loopmax = 100000000;
 {
   timing t;
   for (size_t i = 0; i < loopmax; ++i) {
     try {
       exptest1();
     } catch (...) {
     }
   }
 }
 {
   timing t;
   for (size_t i = 0; i < loopmax; ++i) {
     try {
       exptest2();
     } catch (...) {
     }
   }
 }
 return 0;
}

------- exptiming.h ----------------------------------------

void unknown_func1();
void unknown_func2();

------- unknown.cpp ----------------------------------------

#include "exptiming.h"

int dummy_count = 0;

void unknown_func1()
{
 ++dummy_count;
}

void unknown_func2()
{
 ++dummy_count;
 throw 1;
}

------------------------------------------------------------

使用した最適化オプションは、
VC7.1: /Ox /Og /Ob2 /Oi /Ot /Oy
gcc3.3: -O3 -fomit-frame-pointer
です。
unknown_func1, unknown_func2は、例外を投げるかどうかをコンパイル時に
判断できないようにするために別ファイルに分けてあります。exptest1と
exptest2は、VCとgccのいずれもインライン展開されてループの中に埋め込
まれています。VCの、例外のための「刻印を打つ」オーバヘッドはインラ
イン展開によってかなり軽減されているようです。

[cppll:9352] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9352] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Osamu Shigematsu <m5issige@...>
Date:
Fri, 08 Aug 2003 09:53:04 +0900
X-Mailer:
Becky! ver. 2.06.02
Message-Id:
<20030808094900.E5B4.M5ISSIGE‐at‐mr.hitachi-medical.co.jp>
In-Reply-To:
9350
References:
9349 9350
重松です。こんにちは。

> VCの、例外のための「刻印を打つ」オーバヘッドはインラ
> イン展開によってかなり軽減されているようです。

という点ですが、元の質問からして、当該関数がインライン展開される
可能性はそれほど高くないと思いますし、virtual だったりすると、
インラインに展開されること自体が期待できないので、
このオーバヘッドの軽減は、例外を NULL として返すのか、
throw するのか、この場合のみで考えるのは危険な気もしたりします。

にしても, gcc の例外送出時のコストは大きいですね。

具体的な数値は大変参考になります。
情報 (ソースも)、ありがとうございます。

--
Osamu Shigematsu <m5issige@...>

[cppll:9337] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
9337
Subject:
[cppll:9337] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Tietew <tietew@...>
Date:
Thu, 07 Aug 2003 17:36:23 +0900
X-Mailer:
Becky! ver. 2.06
Message-Id:
<20030807172803.70CD.TIETEW‐at‐tietew.net>
In-Reply-To:
9331
References:
9330 9331
Tietew です。

On Thu, 07 Aug 2003 17:04:19 +0900
In article <200308070811.h778BWQ15266@mailsv3.nec.co.jp>
[[cppll:9331] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール]
FUKUDA Fumiki <fukuda.fm@...> wrote:

> >例外にはどの程度コストがかかるものなのでしょうか。
> >投げた場合も、平穏だった場合も。
>
> 例外飛んだときにたどり着くトコをスタック上に載せて
> おくことになろうかと思います。だから例外が飛ぼうが
> 飛ぶまいが、この刻印を打つのにコストかかりそ。

確かにコストはかかるけど,せいぜいポインタ3〜4つぶんをスタック
に積んだり下ろしたりするだけなので,場合によっては毎回エラー判定
するよりも安かったりしそうです。

例外が投げられたときは,例外スタックを戻りつつスタックを巻き戻す
操作が入るので,結構高コストですが,例外を使わなくても結局自動変
数を破壊しながら登ってゆくことになるので,例外オブジェクトの生成
と型判定処理の分だけコスト増ということになるんじゃないかと。


—[ Tietew ]——— tietew@... / tietew@... ——————
■Tietew Windows Lab.                        http://www.tietew.net/
★C++:language&libraries過去ログ&なまず http://www.tietew.jp/cppll/
PGP fingerprint: 26CB 71BB B595 09C4 0153  81C4 773C 963A D51B 8CAA

[cppll:9332] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9332] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
ANDO Toshihiko <andochin@...>
Date:
Thu, 7 Aug 2003 17:10:42 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1158
Message-Id:
<004001c35cbb$66e7c190$3e00a8c0@hidagyu>
References:
9323
いつもお世話になっております。
安藤@恵比須情報です

> 下記のように、インスタンスを生成して返す関数があります。
>
> CHoge *CreateNewInstance( int type );
>
> この関数内部で例外が発生した場合、、
> もしくは、引数間違いとかがあって、インスタンスを返したくない場合、
> 下記の2通り思いつくのですが、どちらが良いでしょう?
> ・NULLを返す。
> ・例外を発生させる。
> ※場合によってはNullObjectを返すこともあると思いますが。
>

いろんなアプリで使いまわしされるコードならNULLを返す方がいいと思います。
場合によっては例外は使わないでって事もあると思うから。
例外を返したい場合はCreateNewInstanceを呼び出すところで発生させるって感じ
で。
int CreateNewInstance( int type, CHoge** instance);
でエラー情報を返すってしておけば呼び出し側はエラーコードから例外種別を特定し

発生させることもできるし。


> 好み、ポリシーの問題になりそうですが、、、どっちが主流かな?と皆さんの意見
を聞かせてください。
> 他の会社に行った時に通用するように(笑)

他の会社に行くことを考えるなら凝ったC++のソースは書かない方が吉かも。
少なくとも僕はSTLや例外を常用しているような会社の仕事はしたことが無いです
(サポートしてる
コンパイラを使ったプロジェクトでも)。ここのMLに達人がいっぱいいるだけで世
間ではそんなに標
準C++ライブラリやC++の機能は知られていないと思う。

# 時にはベタCのようなソースコードを書いてストレスがたまることもあるからC+
+で自分の使う
# ツールを作ってうさ晴らしをする。


-------------------------------
安藤 敏彦(ANDO Toshihiko)
Mail: andochin@...

[cppll:9333] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9333] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Isapon <mail@...>
Date:
Thu, 7 Aug 2003 17:22:39 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1158
Message-Id:
<00d501c35cbd$1105c130$730210ac@shibuyapc>
References:
9323
いさぽんです。こんにちわ。
そして始めましてですm(_ _)m

> 好み、ポリシーの問題になりそうですが、、、どっちが主流かな?と皆さんの意見
を聞かせてください。

 私の場合ですが、通常NULLを返しますが、引数のミスなど関数の呼び出し側に不具
合がある場合は
例外を返しています(例えば、0か1を渡さなければならない関数に対して2を渡し
た場合など)。

 このような場合、関数の使い方を勘違いしてる可能性が多いので、例外を返したほ
うが分かりやすい
かなぁ…ということで(^^;

 例外起きたら「あ、関数のパラメータ間違ってたか!」と言う感じです。

----------------------------------------------------------------------------
--------
CHoge* CreateNewInstance(int type)
{
   // 引数に間違えがあるかチェック
   if (type > TYPE_MAX)
   {
     // 「そんな呼び出し方しちゃダメです」という意味を込めて例外
     throw CException( E_TYPE_IS_INVALID );
   }

   CHoge*  pResult = 0;
   try {
     // インスタンス生成
   } catch (...) {
     // エラー処理
   }
   return pResult;
}
----------------------------------------------------------------------------
--------

---
isapon : mail@...

[cppll:9335] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9335] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Osamu Shigematsu <m5issige@...>
Date:
Thu, 07 Aug 2003 17:34:43 +0900
X-Mailer:
Becky! ver. 2.06.02
Message-Id:
<20030807173254.E5A4.M5ISSIGE‐at‐mr.hitachi-medical.co.jp>
In-Reply-To:
9333
References:
9323 9333
重松です。こんにちは。

>  私の場合ですが、通常NULLを返しますが、引数のミスなど関数の呼び出し側に不具
> 合がある場合は
> 例外を返しています(例えば、0か1を渡さなければならない関数に対して2を渡し
> た場合など)。
>
>  このような場合、関数の使い方を勘違いしてる可能性が多いので、例外を返したほ
> うが分かりやすい
> かなぁ…ということで(^^;
>
>  例外起きたら「あ、関数のパラメータ間違ってたか!」と言う感じです。

例外って、そういう使い方するものですか?

私の感覚では、

       assert(arg == 0 || arg == 1); // バグなら即死

ですが...。

# バグは例外で処理するものではないと思ふ...。

--
Osamu Shigematsu <m5issige@...>

[cppll:9340] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9340] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
炎羅 <enra@...>
Date:
Thu, 07 Aug 2003 20:37:41 +0900
X-Mailer:
Becky! ver. 2.06.02
Message-Id:
<20030807203733.6F67.ENRA‐at‐mail.interq.or.jp>
In-Reply-To:
9335
References:
9333 9335
こんにちは、炎羅です。

On Thu, 07 Aug 2003 17:34:43 +0900
At [cppll:9335] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
Osamu Shigematsu <m5issige@...> Wrote:

>        assert(arg == 0 || arg == 1); // バグなら即死
> # バグは例外で処理するものではないと思ふ...。

assert関数はスタックアンワインドしてくれないんじゃないでしょうか?
abort関数に行き着いて、後処理を全くせずにterminateだったような覚えが
あります。
そうなると、メモリリークやリソースリークを引き起こす恐れがあるのでは
ないでしょうか?

そんなわけでassert関数の代用として、仕方なく例外を使う事はあると思います。
ただVC++系の場合例外が飛んでも非常に分かりづらいので、何かラッパ関数を
作って、親切なダイアログを出した方がいいかもしれませんけど^^;

■ Written by 炎羅 (enra@...) ■

[cppll:9341] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9341] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Takao Ono <takao@...>
Date:
Thu, 7 Aug 2003 20:43:50 +0900
X-Mailer:
mnews [version 1.22PL5] 2001-02/07(Wed)
Message-Id:
<030807204350.M0115732‐at‐flame.hirata.nuee.nagoya-u.ac.jp>
In-Reply-To:
9340
小野@名古屋大学 です.

<20030807203733.6F67.ENRA@mail.interq.or.jp>の記事において
enra@...さんは書きました。
enra> >        assert(arg == 0 || arg == 1); // バグなら即死
enra> > # バグは例外で処理するものではないと思ふ...。
enra> assert関数はスタックアンワインドしてくれないんじゃないでしょうか?
enra> abort関数に行き着いて、後処理を全くせずにterminateだったような覚えが
enra> あります。
enra> そうなると、メモリリークやリソースリークを引き起こす恐れがあるのでは
enra> ないでしょうか?
「まともな」OS ならプロセスが終了したときにリソースを全て回収する
のでは? だから, メモリリークはしないはず.

ただ, ファイルのロックとかで問題になることはあるかも.
# ロックしちゃったまま終了して「アンロックできね〜」ってことはあ
# りうる.
--
名古屋大学大学院 情報科学研究科 計算機数理科学専攻
小野 孝男

[cppll:9345] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9345] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Takefumi Nakayama <naka@...>
Date:
Thu, 07 Aug 2003 21:42:51 +0900
X-Mailer:
Becky! ver. 2.00.08
Message-Id:
<20030807212623.8A04.NAKA‐at‐reedrex.co.jp>
In-Reply-To:
9341
References:
9340 9341
こんばんは。中山です。

enra> >        assert(arg == 0 || arg == 1); // バグなら即死
enra> > # バグは例外で処理するものではないと思ふ...。

私も、この考え方に賛成です。
ですから、客先リリース時には、assertに引っかかる部分があってはならないはずだし、
そういう意味では、assert後のメモリーリークに関して議論する必要はないかと思います。

でも、例えば、DBのあるフィールドの値によって挙動を変えるインスタンスを返す処理の場合、
仕様変更時にデータパッチを当て忘れて、不正な値が関数に渡されてしまう場合もありますね。
そういう場合は、
(1)例外で処理して、然るべき結果をユーザに示す
(2)データパッチを当てる必要が無いようにコードを書き直す
のどちらかで対処するべきだと考えます。

(2)をやりすぎるとコードがぐちゃぐちゃになるので、NullObjectを返すか、
共通のエラー処理を行うインスタンスを返すか…

どうでしょう?

------------------------------------------------------
CHoge *ret = NULL;
switch( type ){
case 1:
 ret = new CHogeDog
 break;
case 2:
 ret = new CHogeCat
 break;
default:
 ret = new CHogeError
 break;
}
------------------------------------------------------

"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~
中山 剛史 <naka@...>
"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~^"~

[cppll:9353] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
Subject:
[cppll:9353] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Osamu Shigematsu <m5issige@...>
Date:
Fri, 08 Aug 2003 10:05:09 +0900
X-Mailer:
Becky! ver. 2.06.02
Message-Id:
<20030808095417.E5B6.M5ISSIGE‐at‐mr.hitachi-medical.co.jp>
In-Reply-To:
9345
References:
9341 9345
重松です。こんにちは。

> ですから、客先リリース時には、assertに引っかかる部分があってはならないはずだし、
> そういう意味では、assert後のメモリーリークに関して議論する必要はないかと思います。

そういう意味で、assert() は単に普通の (?) ものを引っ張ってきました。

ただ、こういうのって、自分たち開発側でテストを尽くしたつもりでも、
お客さんのところでは、予測もしなかった使い方をして
問題が発生したりするし、なかなか難しいものです。

なので、実際には、ASSERT() というマクロで、引っかかると、
ダイアログを出して、ある程度の死亡位置を確認できるように
工夫したりはしています。

けど、工業製品の場合、ソフトのバグ以外に、装置の故障、もあるわけで、
難しいです。

Microsoft Car じゃないけど、ぶつかりましたがエアバックを作動しますか?
と聞かれて はい をクリックしないと、エアバックが作動しないのも困るし、
壊れるにしても、ブレーキが利かなくなるのではなくて、
ブレーキを解除できなくなるような、安全側に振った壊れ方とか、
死ぬときにも、きれい/安全な死に方を考慮しないといけないケースも
多々あるかと。

--
Osamu Shigematsu <m5issige@...>

[cppll:9346] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール

[ | / | ]
9346
Subject:
[cppll:9346] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール
From:
Tietew <tietew@...>
Date:
Thu, 07 Aug 2003 21:50:33 +0900
X-Mailer:
Becky! ver. 2.06
Message-Id:
<20030807214148.70E4.TIETEW‐at‐tietew.net>
In-Reply-To:
9341
References:
9340 9341
Tietew です。

On Thu, 7 Aug 2003 20:43:50 +0900
In article <030807204350.M0115732@flame.hirata.nuee.nagoya-u.ac.jp>
[[cppll:9341] Re: インスタンスを生成して返す関数内部で例外が発生した時のルール]
takao@... (Takao Ono) wrote:

> enra> そうなると、メモリリークやリソースリークを引き起こす恐れがあるのでは
> enra> ないでしょうか?
> 「まともな」OS ならプロセスが終了したときにリソースを全て回収する
> のでは? だから, メモリリークはしないはず.

メモリリークといえば free-on-exit 論争(読んでないけど…

# 終了にやけに時間がかかると思ったら,大量の要素を抱えた map の
破壊に時間がかかっていた罠,とか。


> ただ, ファイルのロックとかで問題になることはあるかも.
> # ロックしちゃったまま終了して「アンロックできね〜」ってことはあ
> # りうる.

ロックもリソースのうちだから,まともなOSならロックも解放しますね。


というか,Segmentation Fault とかしちゃったら,外部から kill さ
れちゃったら,メモリ不足でカーネルが kill しちゃったら,etc,オ
ブジェクトの回収なんぞ望むべくもないわけで,「終了時」のリソース
リークをそこまで気にすんな,と言いたくもある。

# リリースビルドで気にしたい,というなら判るけど,
# assert ってデバッグビルドだし。

—[ Tietew ]——— tietew@... / tietew@... ——————
■Tietew Windows Lab.                        http://www.tietew.net/
★C++:language&libraries過去ログ&なまず http://www.tietew.jp/cppll/
PGP fingerprint: 26CB 71BB B595 09C4 0153  81C4 773C 963A D51B 8CAA

[cppll:9355] assert 内での || ( was: インスタンスを生成して返す関数内部で例外が発生した時のルール )

[ | / ▼ | ]
Subject:
[cppll:9355] assert 内での || ( was: インスタンスを生成して返す関数内部で例外が発生した時のルール )
From:
Wraith the Trickster <wraith@...>
Date:
Fri, 8 Aug 2003 11:21:59 +0900
X-Mailer:
Microsoft Outlook Express 6.00.2800.1158
Message-Id:
<012c01c35d53$deb1f860$0200a8c0@WindStone>
References:
9323 9333 9335
道化師です。

[cppll:9335] Re: インスタンスを生成して返す関数内部で例外が...】
> assert(arg == 0 || arg == 1); // バグなら即死

スレの趣旨とは関係ないけど、assert 内でこのような || の使い方
は避けませう。このような場合は2つの assert に分割すること推奨
いたしますです。

□■□■                  Wraith the Trickster                  □■□■
■□■□ 〜I'll go with heaven's advantage and fool's wisdom.〜 ■□■□

Navigation

検索

[検索ヘルプ]

Maintener: Tietew <www.tietew.jp>
Powered by Ruby on Rails, Mongrel, PostgreSQL, and Hyper Estraier.
click here