C++のメンバ関数で「if(!this)」はどれくらいまずいのか?
質問
もし、古いコードで
if (!this) return;
を使用する古いコードを見つけた場合、どの程度深刻なリスクとなるでしょうか。それとも、静かにそのままにしておくことができるコードの臭いのようなものでしょうか。
私は 書く コードを書くつもりはありません。むしろ、私たちのアプリの多くの部分で使用されている古いコア ライブラリで、最近何かを発見しました。
を想像してみてください。
CLookupThingy
クラスが
非仮想的な
CThingy *CLookupThingy::Lookup( name )
メンバ関数があります。どうやら、当時のプログラマーの一人は、NULL CLookupThingy *
が関数から渡される多くのクラッシュに遭遇し、何百もの呼び出しサイトを修正するよりも、彼は静かに Lookup() を修正しました。
CThingy *CLookupThingy::Lookup( name )
{
if (!this)
{
return NULL;
}
// else do the lookup code...
}
// now the above can be used like
CLookupThingy *GetLookup()
{
if (notReady()) return NULL;
// else etc...
}
CThingy *pFoo = GetLookup()->Lookup( "foo" ); // will set pFoo to NULL without crashing
今週初めにこのgemを発見したのですが、今、修正すべきかどうかで葛藤しています。これは、私たちのすべてのアプリで使用されるコア ライブラリにあります。これらのアプリのいくつかは、すでに何百万人もの顧客に出荷されており、そのコードからクラッシュやその他のバグが発生することはなく、正常に動作しているようです。このコードからクラッシュやその他のバグが発生することはありません。
if !this
を削除することは、NULL を渡す可能性のある何千もの呼び出しサイトを修正することを意味します。必然的にいくつかは見落とされ、次の
年
の開発期間中にランダムに発生します。
だから、どうしても必要なとき以外は、放っておきたい気持ちもあるんです。
技術的に未定義の動作であることを考えると、どの程度危険なのかというと
if (!this)
は実際どの程度危険なのでしょうか?修正するために何週間もの労力を費やす価値があるでしょうか、それとも MSVC と GCC は安全に戻ることを期待できるでしょうか?
私たちのアプリケーションは MSVC と GCC でコンパイルされ、Windows、Ubuntu、および MacOS で実行されます。他のプラットフォームへの移植性は関係ありません。問題の関数は、決して仮想でないことが保証されています。
編集してください。 私が求めている客観的な回答は、次のようなものです。
- 現在のバージョンの MSVC と GCC は、非仮想メンバが暗黙の 'this' パラメータを持つ静的関数であるような ABI を使用しているので、'this' が NULL であっても安全に関数に分岐します。
- 次のバージョンの GCC では、非仮想関数でさえクラスポインタから分岐ターゲットをロードする必要があるように ABI が変更される予定です。
- 現在の GCC 4.5 は、非仮想的なメンバーを暗黙のパラメーターによる直接分岐としてコンパイルすることもあれば、クラス オフセット関数ポインターとしてコンパイルすることもあるという矛盾した ABI を備えています。
前者は、コードが臭いけれども壊れそうにないことを意味し、後者はコンパイラーのアップグレード後にテストするもので、後者は高いコストをかけてもすぐに対処する必要があります。
明らかに、これは起こるのを待っている潜在的なバグですが、今は、私たちの特定のコンパイラーでのリスクを軽減することにのみ関心があります。
どのように解決するのですか?
私なら、そのままにしておきます。これは、古風なバージョンとして意図的に選んだのかもしれません。 SafeNavigationOperator . おっしゃるとおり、新しいコードではお勧めしませんが、既存のコードではそのままにしておきます。もし修正するのであれば、そのコードへのすべての呼び出しがテストによって十分にカバーされていることを確認する必要があります。
編集から追加: あなたは は を通して、デバッグバージョンのコードでのみ削除することを選択できます。
CThingy *CLookupThingy::Lookup( name )
{
#if !defined(DEBUG)
if (!this)
{
return NULL;
}
#endif
// else do the lookup code...
}
このように、デバッグモードでテストする機会を与えつつ、本番コード上では何も壊さないでしょう。
関連
-
[解決済み] 文字列の単語を反復処理するにはどうすればよいですか?
-
[解決済み] using namespace std;」はなぜバッドプラクティスだと言われるのですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] Linux上で動作するC++コードのプロファイリングを行うにはどうすればよいですか?
-
[解決済み] C++テンプレート関数定義の.CPPファイルへの格納
-
[解決済み] noexceptを本当に使うべきはいつですか?
-
[解決済み] 関数からunique_ptrを返す
-
[解決済み】パブリックフレンドスワップメンバー関数
-
[解決済み] 強化されたGCC 6オプティマイザは、なぜ実用的なC++コードを壊すのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】Visual Studio 2015で「非標準の構文。'&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】エラー:free(): 次のサイズが無効です(fast)。
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された
-
[解決済み] NULLインスタンスに対してメンバ関数を呼び出すと、どのような場合に未定義の動作となるのですか?
-
[解決済み] assert()の呼び出しを完全に無効にするにはどうすればよいですか?