web-dev-qa-db-ja.com

メッセージ付きのassert()

私はどこかで次のようにメッセージでアサートが使用されているのを見ました:

assert(("message", condition));

これは、gccが次の警告をスローすることを除いて、うまく機能しているようです。

warning: left-hand operand of comma expression has no effect

警告を停止するにはどうすればよいですか?

39
Alexandru

警告を停止するには、-Wno-unused-valueを使用します。 (オプション-Wallには-Wunused-valueが含まれます)。

次のような別の方法を使用する方が良いと思います

assert(condition && "message");
70
pmg

試してください:

#define assert__(x) for ( ; !(x) ; assert(x) )

そのまま使用:

assert__(x) {
    printf("assertion will fail\n"); 
}

アサートが失敗した場合にのみブロックを実行します。

重要な注意:このメソッドは、xが評価される場合、式xを2回評価しますfalse(最初はforループがその条件をチェックしているとき、2回目はassertが渡された式を評価しているとき!)

21
bugfeeder

フォーマットされたメッセージを渡したい場合は、次のマクロを使用できます。

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <assert.h>

#define clean_errno() (errno == 0 ? "None" : strerror(errno))
#define log_error(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__)
#define assertf(A, M, ...) if(!(A)) {log_error(M, ##__VA_ARGS__); assert(A); }

次に、printfのように使用します。

// With no args
assertf(self != NULL,"[Server] Failed to create server.");

// With formatting args
assertf((self->socket = u_open(self->port)) != -1,"[Server] Failed to bind to port %i:",self->port);
// etc...

出力:

[エラー](../src/webserver.c:180:errno:アドレスはすでに使用されています)[サーバー]ポート8080へのバインドに失敗しました:webserver:../src/webserver.c:180:server_run:アサーション `( self-> socket = u_open(self-> port))!= -1 'が失敗しました。

http://c.learncodethehardway.org/book/ex20.html に基づく

12
frmdstryr

伝統により、(void)は、意図的に式を無視していることをコンパイラに通知します。

/* picard.c, TNG S6E11. */
#define assertmsg(x, msg) assert(((void) msg, x))
assertmsg(2+2==5, "There! are! four! lights!");
0
Arthur2e5

_Static_assert(expr, msg)と同じ使用法を提供する独自のマクロを作成できます。

_#include <assert.h>
#include <stdbool.h>
#include <stdio.h>


/*
 * void assert_msg(bool expr, const char *msg);
 */
#if !defined(NDEBUG)
#define assert_msg(expr, msg)   do                  \
{                                                   \
        const bool  e_ = expr;                      \
                                                    \
        if (!e_) {                                  \
                fputs(msg, stderr);                 \
                fputc('\n', stderr);                \
                assert(e_);                         \
        }                                           \
} while (0)
#else
#define assert_msg(expr, msg)   do                  \
{                                                   \
                                                    \
        if (!(expr))                                \
                warn_bug(msg);                      \
} while (0)
#endif
_

アサーションが無効になっている場合でも、プログラムの名前、ファイル、行、関数、errno値と文字列、およびユーザーメッセージを出力するマクロwarn_bug()もあります。その背後にある理由は、それがプログラムを壊すことはありませんが、バグがおそらく存在するであろうことを警告するでしょう。ただし、defined(NDEBUG)の場合、_assert_msg_を空に定義するだけで済みます。

0
Cacahuete Frito

const char*を受け取ってtrueを返す関数は、おそらくあらゆる種類の警告からあなたを救うでしょう:

#include <assert.h>

int always_true(const char *msg) {
    return 1;
}

#define assert_msg(expr, msg) assert((expr) && always_true(msg))
0
JiaHao Xu