Инструмент для автоматической генерации проверки кода возврата - PullRequest
0 голосов
/ 28 октября 2011

Я ищу инструмент, который генерирует подпрограмму для проверки кода возврата какой-либо другой подпрограммы.

Например, pthread_create может вернуть 0, EAGAIN, EINVAL и EPERM коды.Было бы неплохо иметь такую ​​проверку:

void pthread_create_check(int retcode) {
    switch (retcode) {
    case 0:
        printf("pthread_create success.\n");
        break;
    case EAGAIN:
        printf("pthread_create EAGAIN error: insufficient resources"
               " to create another thread, or a system-imposed"
               " limit on the number of threads was encountered.\n");
        break;
    case EINVAL:
        printf("pthread_create EINVAL error: invalid settings in"
               " attr.\n");
        break;
    case EPERM:
        printf("pthread_create EPERM error: no permission to set the"
               " scheduling policy and parameters specified in"
               " attr.\n");
        break;
    }
}

И использовать ее таким образом:

iret = pthread_create(&thread_desc, 
                      NULL, 
                      thread_function, 
                      (void *) thread_param);
pthread_create_check(iret);

На man-странице есть объяснение каждого кода ошибки.Создание такого средства проверки - не что иное, как коды ошибок копирования и вставки и объяснение со страницы руководства.Я думаю, что компьютер может сделать эту работу намного лучше, чем человек, так как компьютер никогда не утомляется.Кроме того, мне лень делать это для каждого вызова подпрограммы.Есть ли какой-нибудь инструмент автоматизации?

Ответы [ 2 ]

2 голосов
/ 28 октября 2011

Просто создайте таблицы сообщений. Это сэкономит время и пространство кодирования.

typedef struct pthread_message {
    int code;
    const char* text;
} pthread_message;

int pthread_check(int retcode, const char* fname, 
    pthread_message* messages)
{
    if(!retcode) /* Makes the common case fast. */
    {
        fprintf(stderr, "%s success.\n", fname);
        return retcode;
    }

    /* Look for a message. */
    for(; messages->code; ++messages)
        if(messages->code == retcode)
        {
            fprintf(stderr, "%s %s\n", fname, message->text);
            return retcode;
        }

    /* Fall back on standard library. If you lack strerror_r, 
       then put a generic message here.
    */
    char buf[256];
    fprintf(stderr, "%s %s\n", fname, strerror_r(retcode, buf, 256));
    return retcode;
);

pthread_message pthread_create_messages[] = {
    { EAGAIN, "EAGAIN error: insufficient resources to create another thread,"
      " or a system-imposed limit on the number of threads was encountered." },
    { EINVAL, "EINVAL error: invalid settings in attr." },
    { EPERM, "EPERM error: no permission to set the scheduling policy and"
      " parameters specified in attr." },
    { 0, 0 } /* End of list. */
};

iret = pthread_check(pthread_create(arg1, arg2, ...), "pthread_create", 
    pthread_create_messages);

Ничто не мешает вам делиться списками сообщений между функциями, поэтому вы можете писать столько, сколько хотите.

Если вы ненормальный, вы можете сделать из вызова макрос:

#define PTHREAD_CHECK(fname, arglist) \
    (pthread_check(fname arglist, #fname, fname##_messages))

iret = PTHREAD_CHECK(pthread_create, (arg1, arg2, ...));

В этом случае разделение списка сообщений означает, что вам нужно создать указатель с соответствующим именем для каждой дополнительной функции, указывающей на список первой функции. Еще намного меньше работы.

Для справки, я просто написал одну функцию проверки с общими сообщениями (за исключением сообщений об успехе, они являются спамом) и использовал ее везде в моей оболочке C ++ вокруг pthread. (Не придирайтесь ко мне по поводу Boost, это было десять лет назад.)

1 голос
/ 28 октября 2011

Helgrind от Valgrind может обнаруживать злоупотребления API pthreads POSIX.

http://valgrind.org/docs/manual/hg-manual.html#hg-manual.api-checks

...