21

つまり、コードに有用なアサーションを含めるにはどうすればよいでしょうか?

MFC は非常に簡単です。ASSERT(何か)を使用するだけです。

非 MFC の方法は何ですか?

編集: assert() を呼び出したファイルではなく、assert.c でアサートの破損を停止することは可能ですか?

編集:<assert.h> &の違いは何<cassert>ですか?

受け入れられた回答:この投稿には素晴らしい回答がたくさんあります。複数の回答を受け入れることができたらいいのにと思います (または、誰かがそれらすべてを組み合わせてくれるでしょう)。したがって、回答はフェルッチョに授与されます(最初の回答に対して)。

4

11 に答える 11

29
#include <cassert>

assert(something);

コンパイル時のチェックには、Boost の静的アサートが非常に便利です。

#include <boost/static_assert.hpp>

BOOST_STATIC_ASSERT(sizeof(int) == 4);  // compile fails if ints aren't 32-bit
于 2008-10-07T18:23:00.360 に答える
13

Visual C++ 以外で動作するものを探しているかどうかによって異なります。また、探しているアサーションのタイプによっても異なります。

アサーションにはいくつかのタイプがあります。

  1. プリプロセッサ
    これらのアサーションは、プリプロセッサ ディレクティブを使用して実行され#error
    ます。プリプロセッサ アサーションは、前処理段階でのみ評価されるため、テンプレートなどには役立ちません。

  2. 実行時
    これらのアサーションは、実行時アサーションassert()で定義された関数を使用して実行され、<cassert>
    実行時にのみ評価されます。また、BoltBait が指摘したように、NDEBUGマクロが定義されている場合はコンパイルされません。

  3. 静的
    これらのアサーションは、あなたが言ったように、ASSERT()マクロを使用して行われますが、MFC を使用している場合のみです。C/C++ 標準の一部である静的アサーションを行う別の方法は知りませんが、Boost ライブラリは別の解決策を提供していますstatic_assert
    Boost ライブラリの関数は、 C++0x 標準static_assertに追加される予定のものです。

追加の警告として、Ferruccio が提案した関数は、MFCマクロassert()と同じ動作をしません。ASSERT()前者は実行時アサーションで、後者は静的アサーションです。

これが役立つことを願っています!

于 2008-10-07T19:03:27.520 に答える
10

アサートは(通常)デバッグのみです

「アサート」の問題は、通常はデバッグ バイナリにあり、一部の開発者は、コードがまだ本番環境にあるかのように使用することです。

コードは集中的にテストされるはずなので、これ自体は悪ではありません。したがって、アサートを生成するバグは確実に発見され、削除されます。

しかし、場合によっては (ほとんどの場合?)、テストが必要なほど集中的ではないことがあります。最後の最後までコーディングしなければならなかった古い仕事については話しません (聞かないでください... 時々、マネージャーはただ... ええと... )... assert のポイントは何ですか?次の分にクライアントにリリース バイナリとしてコンパイルおよび配信されるコードに追加しますか?

(いくつかの) 実際のアプリケーションでアサートする

私たちのチームでは、エラーを検出するための何かが必要でしたが、同時にエラーを処理するための何かが必要でした。そして、Release Build でそれが必要になる可能性がありました。

Assert は、デバッグ ビルドでのみエラーを検出して処理します。

そのため、代わりに XXX_ASSERT マクロと XXX_RAISE_ERROR マクロを追加しました。

XXX_ASSERT マクロは ASSERT マクロと同じことを行いますが、デバッグとリリースの両方でビルドされます。その動作 (ログを書き込む、メッセージボックスを開く、何もしないなど) は .INI ファイルで制御でき、その後、アプリケーションを中止/終了します。

これは次のように使用されました。

bool doSomething(MyObject * p)
{
   // If p is NULL, then the app will abort/exit
   XXX_ASSERT((p != NULL), "Hey ! p is NULL !") ;
   
   // etc.
}

XXX_RAISE_ERROR マクロは、エラーを「記録」するだけで、それを処理しようとはしませんでした。これは、メッセージをファイルに記録したり、MessageBox を開いてメッセージを表示したり、続行するためのボタンや、(.INI ファイルの構成に従って) デバッグ セッションを開始するための別のボタンを開いたりできることを意味します。これは次のように使用されました。

bool doSomething(MyObject * p)
{
   if(p == NULL)
   {
      // First, XXX_RAISE_ERROR will alert the user as configured in the INI file
      // perhaps even offering to open a debug session
      XXX_RAISE_ERROR("Hey ! p is NULL !") ;
      // here, you can handle the error as you wish
      // Than means allocating p, or throwing an exception, or
      // returning false, etc.
      // Whereas the XXX_ASSERT could simply crash.
   }
   
   // etc.
}

私たちのライブラリに導入されてから 1 年後、XXX_RAISE_ERROR のみが使用されています。もちろん、アプリのタイム クリティカルな部分では使用できません (そのための XXX_RAISE_ERROR_DBG があります) が、それ以外の場合は問題ありません。また、好みのエラー処理を使用でき、開発者のコ​​ンピューター、テスター、またはユーザーのいずれかで自由にアクティブ化できるという事実は、非常に役立ちます。

于 2008-10-07T21:22:27.893 に答える
9

2番目の「編集」で質問に答えるには:

< assert.h> は C ヘッダーです

< cassert> は C++ 標準ライブラリのヘッダーです ... 通常は < assert.h> が含まれます

于 2008-10-07T18:42:07.797 に答える
7

基本的なアサートの使用法

#include <cassert>

/* Some code later */
assert( true );

ベスト プラクティス ノート

アサートは、 true であるべきランタイム状態を識別するために使用されます。その結果、リリース モードでコンパイルされます。

assert を常にヒットさせたい場合は、false を渡すことができます。例えば:

switch ( someVal ):
{
case 0:
case 1:
  break;
default:
  assert( false ); /* should never happen */
}

assert を介してメッセージを渡すこともできます。

assert( !"This assert will always hit." );

成熟したコードベースは、アサート機能を拡張することがよくあります。一般的な拡張子には次のものがあります。

  • モジュールごとにアサートを切り替えて、テストをローカライズします。
  • ほとんどのデバッグ ビルドでコンパイルされる追加の assert マクロを作成します。これは、非常に頻繁に (1 秒あたり数百万回) 呼び出され、正しくない可能性が低いコードに適しています。
  • ユーザーが現在ヒットしているアサート、コンパイル ユニット内のすべてのアサート、またはコードベース内のすべてのアサートを無効にできるようにします。これにより、無害なアサートがトリガーされ、使用できないビルドが作成されるのを防ぎます。
于 2008-10-07T19:06:09.090 に答える
6

アサーションを呼び出したファイルの内部に侵入するには、例外をスローするか、次を呼び出すカスタムマクロを使用できます__debugbreak

#define MYASSERT(EXPR, MSG) if (!(EXPR)) throw MSG;

または:

#define MYASSERT(EXPR) if (!(EXPR)) __debugbreak();
于 2008-10-07T18:36:34.437 に答える
5

Microsoft 固有の CRT アサート

#include <crtdbg.h>
#include <sstream>
...
// displays nondescript message box when x <= 42
_ASSERT(x > 42);
// displays message box with "x > 42" message when x <= 42
_ASSERTE(x > 42);
// displays message box with computed message "x is ...!" when x <= 42
_ASSERT_EXPR(
   x > 42, (std::stringstream() << L"x is " << x << L"!").str().c_str());
于 2008-10-07T19:56:39.020 に答える
3

Visual C++ と gcc の両方で動作するアサーションを持つ、ModAssert と呼ばれるより高度なオープン ソース ライブラリがあります。おそらく他のコンパイラでも同様ですが、確かなことはわかりません。習得には時間がかかりますが、MFC に依存しない優れたアサーションが必要な場合は、これらを参照してください。http://sourceforge.net/projects/modassert/にあります。

于 2009-11-17T08:48:23.600 に答える
1

質問者の 3 番目の質問に答えるには、「assert.h」の代わりに「cassert」を使用する最初の理由は、C++ の場合、C++ コンパイラが関数の記述をコードに格納しない可能性があるという事実が考慮されているためです。ファイルですが、dll またはコンパイラ自体にあります。2 つ目は、現在または将来、C と C++ の違いを容易にするために、関数にマイナーな変更が加えられる可能性があることです。assert.h は C ライブラリであるため、C++ では「cassert」を使用することをお勧めします。

于 2014-11-20T07:40:24.743 に答える
1

IntelliSense を使用して Visual Studio で開きます (右クリック)。

// cassert standard header
#include <yvals.h>
#include <assert.h>

yvals.h は Windows のものです。したがって、assert() 自体に関する限り、それを含める 2 つの方法は同じです。多くの場合、それほど単純ではないため、 を使用することをお勧めし<cxxx>ます (名前空間のラッピングやその他の魔法)。

これは私にとって呼び出し元のサイトで壊れます...

このマクロを自分で書きたくない理由を説明する記事を次に示します。

于 2008-10-07T18:55:24.617 に答える
1

これは、C++ でのアサーション機能の最新のイテレーションです: http://pempek.net/articles/2013/11/17/cross-platform-cpp-assertion-library/

これは、プロジェクトに簡単に追加できるドロップイン 2 ファイル ライブラリです。

于 2014-02-10T20:26:46.580 に答える