用于自动生成返回码检查器的工具

时间:2011-10-28 13:39:04

标签: c code-generation static-analysis

我正在寻找一个工具,它可以生成子程序来检查其他子程序的返回代码。

例如,pthread_create可以返回0EAGAINEINVALEPERM代码。有这样的检查器会很高兴:

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);

手册页中有每个错误代码的说明。创建这样的检查器只是复制粘贴错误代码和手册页中的解释。我认为计算机可以比人类更好地完成这项工作,因为计算机永远不会厌倦。而且,我懒得为每个子程序调用做这件事。有没有自动化工具?

2 个答案:

答案 0 :(得分: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,这是十年前的事。)

答案 1 :(得分:1)

Valgrind的Helgrind可以检测到POSIX pthreads API的误用。

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