を避けるnullポインタの例外の大規模なc++のコードベース
-
19-09-2019 - |
質問
していま継承した大型のc++のコードベースとしてタスクを避けたnullポインタを除外できることのないドラインをサポートしています。はりの静的解析ツールのご利用で、私の考え方を維持し、使用が成功しました。
何でもいいですか?
解決
あなたがNULLの発生源をなくすことで起動することができます:
変更
if (error) {
return NULL;
}
の中へ
if (error) {
return DefaultObject; // Ex: an empty vector
}
デフォルトのオブジェクトを返すことは適用し、あなたのコードベースがすでに例外を使用しない場合は、行います。
if (error) {
throw BadThingHappenedException;
}
次に、適切な場所での取り扱いを追加します。
あなたはレガシーコードを使用している場合、あなたには、いくつかのラッパー関数/クラスを作ることができます:
ResultType *new_function() {
ResultType *result = legacy_function();
if (result) {
return result;
} else {
throw BadThingHappenedException;
}
}
の新機能は、新しい機能の使用を開始し、適切な例外処理を持っている必要があります。
私はいくつかのプログラマが知っているだけでジョエルのようなスマートな人を含め、例外を得ることはありませんに。しかし、何NULLを返すことによって起こっ終わると、このNULLは、誰もがそれはそれを処理し、静かに返すために彼らのビジネスではないと思いますので、狂ったように周りに渡すなるということです。いくつかの関数は結構です、エラーコードを返すことがありますが、呼び出し側は、多くの場合、エラーに応じて、まだ別の-NULLを返してしまいます。その後、あなたは関数であるどんなに些細な、すべての単一の関数でNULLチェックの多くを参照してください。そして、それが取るすべてはNULLがプログラムをクラッシュさせるかどうかをチェックしませんただ一つの場所です。例外は慎重にエラーを考えると、正確にどこで、どのようにそれを扱うべきを決定するためにあなたを強制します。
あなただけ(あなたが常に使用する必要があります)静的解析ツールのような簡単な解決策を探しているように、それはそうです。参照へのポインタを変更すると、あまりにも偉大なソリューションです。しかし、C ++が持つ必要がなくなりRAIIの美しさを、持ってどこにでも、私はそれがあなたの真剣な検討をworthsだと思う「ついに{}} {みてください」。
他のヒント
あなたは主にコードベース、最低レベルの努力の一つを維持しているし、あなたがすることができる最高のリターンのものは<のhref = "http://en.wikipedia.org/に自分の裸のポインタをリファクタリング開始している場合ウィキ/ Reference_counting」REL = "nofollowをnoreferrer">参照はポインタをカウントします。
最初に、技術のポイントはC++がないNULLポインタが例外をスローしました。Dereferencing NULLポインタが未定義の動作は、ほとんどのシステムのプログラムが突然終了す("墜落").
しのためのツールを、私もお勧めの質問:
いてC++の静的コード分析ツールを原作に忠実(キャラらしさ)
に関するNULLポインタdereferences特に、と考えるNULLポインター逆参照することによって要素
- の導入にNULLポインタです。
- の流れとポインタを他のプログラム。
- の逆参照のこのポインタです。
の静的解析ツールはもちろんステップ2は、ツールの差別化によりどのように複雑な経路で正確に、多くの誤検知)します。すために有効と考えられるあの具体例としてはバグのいくため、より良いごうツールに効果的である。
免責事項:働いていたCoverity.
(他の回答を参照してください)。しかし、あなたはいくつかの小さなBuggersを見つけるために使用することができますちょっといいMakro-定義がある(あなたがそれを使用する機能にポインタを置く)問題の特別な部分のために: (リリースモードでない時のオーバーヘッド及びコードに目に見える状態を追加)
#ifdef NDEBUG
#define NotNull(X) X
#else // in Debug-Mode
template<typename T> class NotNull;
template<typename T> // template specialization only for pointer-types
class NotNull<T*> {
public:
NotNull(T* object)
: _object(object) {
assert(object);
}
operator T*() const {
return _object;
}
T* operator->() const {
return _object;
}
private:
T *_object;
};
#define NotNull(X) NotNull<X>
#endif // in Debug-Mode
あなたはただこのことから、すべての機能を変更します。
void increase(int* counter)
{ .. }
これに
void increase(NotNull(int*) counter)
{ .. }
p.s:最初の HERE発見し、さらに
微調整することができます側の質問、彼らは顧客がクラッシュを表示したくないので、これらを回避する目的は何ですか?多くの場合、ヌルポインタはすぐに処理しなければならない予想外の条件がありますが、あまりにも頻繁に彼らはホットポテトのようなシステムに通します。
私は一度戻り、任意のヌルポインタにし、そうであれば最初のチェックに、習慣は関数へのエントリ時たコードベースに取り組みました。クラッシュしていなかったツールは、それが最終的に静かに不正なデータを生成しながら、これで問題があります。そして、不法にヌルポインタが多くの機能スルー昔から渡されるがあった可能性があるため、結果は耐え難いなったか、最終的に顕在化していた前に、これらの問題は難しかったデバッグしようとしています。
理想的には、あなたの開発期間中に少なくとも適切な表明をしたいので、非表示にしたり、生産を構築するためにアサートを再定義するマクロを考える