Інструмент для автоматичного створення перевірки повернення коду

Я шукаю інструмент, який генерує підпрограму для перевірки коду повернення деякої іншої підпрограми.

Наприклад, 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. Створення такого контролера - це не що інше, як копіювати копії помилок і пояснити з сторінки man. Я думаю, що комп'ютер може зробити цю роботу набагато краще, ніж людина, оскільки комп'ютер ніколи не отримує шини. Крім того, я занадто ледачий робити це для кожного виклику підпрограми. Чи є інструмент автоматизації?

0
прохання роз'яснити: ви хочете мати загальний код генератор, який генерує перевірку коду повернення для будь-якого виклику бібліотеки з сторінки man? (_У цьому випадку (а) удача (b) моєю найкращою рекомендацією буде чудовий інтерфейс ptrace для перехоплення викликів під час виконання)
додано Автор sehe, джерело
Це не неможливо, але це далеко поза практичним. Причина полягає в тому, що не існує стандартного форматування кодів помилок на сторінках man . Ці сторінки призначені для читання людиною, а не машинами, тому вони не перевіряються. Крім того, формулювання не те саме, що ви хочете бачити в повідомленні про помилку. Звичайно, якщо ви маєте доступ до подібної інформації про компанію Watson від IBM, ви можете мати постріл.
додано Автор Mike DeSimone, джерело
Так, я хочу генератор коду. Я буду щасливий навіть з негенеричним генератором, який розуміє загальні підпрограми, напр. fopen , mq_send . Чому, на вашу думку, це неможливо?
додано Автор Kirill, джерело

2 Відповіді

Просто зробіть таблиці повідомлень. Це заощадить час і простір кодування.

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, це було десять років тому.)

2
додано
Немає достатньої узгодженості у форматуванні man page, щоб зробити такий інструмент можливим. Розбір добре сформованого входу - це велика робота сама по собі; додавання всього коду для обробки незвичайних речей призведе до того, що ви вкладете в проект набагато більше зусиль, ніж просто копіювати та вставляти повідомлення та робити таблиці, як описано вище. У реальному житті звичайним є те, що люди ігнорують коди помилок і сподіваються на краще (BAD!), Після чого перевіряють на ненульове значення і при необхідності викликають strerror . Іноді вони роблять макрос, який використовує __FILE__ і __LINE__ , щоб повідомити, де невдалий виклик містився в коді.
додано Автор Mike DeSimone, джерело
TL, DR: Ви вкладаєте в це набагато більше зусиль, ніж більшість програмістів в реальному житті, так що я буду турбуватися про перевищення, витрачаючи весь свій час на обробку помилок, а не на кодування фактичної програми. Шукайте баланс.
додано Автор Mike DeSimone, джерело
Дуже цікавий підхід! Це зменшує обсяг роботи, але ще є багато рутинних. Ваш профіль говорить, що ви дуже досвідчений розробник C ++. Що ви думаєте про інструмент, який генерує шашки з чоловічих сторінок? Це корисно? Який підхід використовується в реальному кодуванні?
додано Автор Kirill, джерело
Дякуємо за відповідь та коментарі! Думка досвідченої людини незамінна.
додано Автор Kirill, джерело

Helgrind Valgrind може виявити неправильне використання API pіthreads POSIX.

http://valgrind.org/docs/manual/hg -manual.html # hg-manual.api-перевірки

1
додано
Хм, Valgrind є потужним інструментом. Чи має він подібну функціональність для інших звичайних підпрограм, наприклад, fopen ?
додано Автор Kirill, джерело