2

今日、職場で比較的単純な C コードに取り組んでいるときに、少し空想にふけるようになり、エラー メッセージを効果的に生成する次のライブラリを作成しました。perror陪審員はまだ出ていません-少なくとも私の心では-これが単に目的に適応するよりも効果的なアプローチであるかどうかerrno...それは「ライブラリ」である必要さえまったくなく、むしろ単なるセットですマクロ。

今のところ、私はライブラリを呼び出していますelib:

elib.h

#ifndef _ELIB_H_
#define _ELIB_H_

struct ErrorMap {
    void (*fp);
    int errorCode;
    char * message;
};

#define eperror(...) fprintf(stderr,  ##__VA_ARGS__)
char * getErrorMsg(struct ErrorMap *, void (*fp), int);

#endif /* _ELIB_H_ */

elib.c

#include <stdlib.h>
#include "elib.h"

char * getErrorMsg(struct ErrorMap * errorMap, void (*fp), int code)
{
    int i;
    // TODO: Replace naive search
    for (i=0; errorMap[i].fp != NULL; i++)
    {
        if (errorMap[i].fp == fp && errorMap[i].errorCode == code)
        {
            return errorMap[i].message;
        }
    }
    return NULL;
}

test.c (サンプルアプリ「xyzlib」)

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

#include "elib.h"

int xyzlib_openFile(int);
int xyzlib_putStuff(char *);

static struct ErrorMap xyzlib_ErrorMap [] = {
    {xyzlib_openFile, -1, "Argument is less than 3"},
    {xyzlib_putStuff, -1, "Argument is NULL"},
    {xyzlib_putStuff, -2, "Length of argument is 0"},
    {xyzlib_putStuff, -3, "Stuff is too long"},
    {NULL, 0, NULL}
};


int xyzlib_openFile(int fd)
{
    if (fd > 3)
    {
        return (-1);
    }

    // open a file.. or something.

    return 0;
}

int xyzlib_putStuff(char * stuff)
{
    if (stuff == NULL)
    {
        return (-1);
    }

    if (strlen(stuff) == 0)
    {
        return (-2);
    }

    if (strlen(stuff) > 3)
    {
        return (-3);
    }

    // do something ...

    return (0);
}


int main(int argc, char ** argv)
{
    int code;

    if (argc != 2)
    {
        printf("Usage: %s <arg>\n", argv[0]);
        return 1;
    }

    code = xyzlib_putStuff(argv[1]);

    if (code < 0)
    {
        eperror("Error: %s\n", getErrorMsg(xyzlib_ErrorMap, xyzlib_openFile, code));    
    }
}

基本的に、ErrorMap テーブルでリターン コードを定義/登録します。エラー表示 (応答値 < 0) を受け取った場合、getErrorMsgは登録されたテーブルを調べて対応するコードと関数を探し、適切なメッセージを取得します。エラー報告にこのアプローチを採用している特定のライブラリの場合、(グローバルではなく) 関数ごとにエラー コードを定義できるため、すべてのコードの管理が簡素化されます。

ただし、適切なメッセージを検索するための小さなオーバーヘッドに加えて、このアプローチを採用するすべての C コードでは、すべての関数 (非負の整数を返さない) がints を返し、最初の引数をへのポインターとして使用する必要があります。戻り値 -- 少し慣用的ではありませんが、一般的に使用されます。

ターゲット市場が信頼性の高い組み込みデバイス用のソフトウェアであるとしましょう (ただし、リソースの制約はそれほど大きくありません)。

何かご意見は?前もって感謝します。

4

1 に答える 1

1

これには意味がありません、ごめんなさい。多分それは、C でエラー コードを処理する方法が原因です。基本的には、エラー値を単一モジュールのインターフェイスの一部として定義します。モジュール間のエラーは衝突します。つまり、2 つのモジュールが異なるエラー コードに対して同じ数値を持っているかどうかは気にしません。さまざまな列挙型の強力な型チェックを取得するには、通常、それらを構造体にラップします。しかし、私はあなたのアプローチのように思われる各関数に固有のエラーコードを作成することを本当に気にしません.

繰り返しますが、これは私の固有のものですが、他の方法で行う必要性を実際に感じたことはありません. モジュール全体に対して定義されたエラー コードは、通常、このモジュールを実装するプロシージャ間で渡されるのに適しています。関数ではなく、モジュールの境界にアプローチを実際にマッピングできるとしたらどうでしょうか? :)

于 2012-05-15T04:35:37.070 に答える