C 检测向未初始化变量传递指针

C 检测向未初始化变量传递指针,c,pointers,initialization,coccinelle,C,Pointers,Initialization,Coccinelle,有些函数有一个指针参数,指向结果的来源 调用函数应该被存储,但函数也需要 调用函数时,此指针指向用作输入值的某个值 (例如,输入/输出参数) 我想检测这样的情况,即调用指向未初始化变量的函数。 应该能够做到这一点,但我努力了一点,以实现这一点 目标代码示例: #include <string.h> #include <stdio.h> static void cartoon_random_generator(int *n) { switch (*n) {

有些函数有一个指针参数,指向结果的来源 调用函数应该被存储,但函数也需要 调用函数时,此指针指向用作输入值的某个值 (例如,输入/输出参数)

我想检测这样的情况,即调用指向未初始化变量的函数。 应该能够做到这一点,但我努力了一点,以实现这一点

目标代码示例:

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

static void cartoon_random_generator(int *n)
{
    switch (*n) {
    case 4:
        *n = 4; /* http://xkcd.com/221/ */
        break;
    case 9:
        *n = 9; /* http://dilbert.com/strips/comic/2001-10-25/ */
        break;
    default:
        fprintf(stderr, "*n was not initialized before calling this function\n");
        break;
    }
}
/* alternative links http://i.stack.imgur.com/VvTef.png and http://i.stack.imgur.com/u0iJ7.gif */

static void test(const char *cartoon)
{
    // not ok, missing
    {
        int n1;

        cartoon_random_generator(&n1);
        printf("Random number = %d\n", n1);
    }

    // ok, declaration
    {
        int n2 = 4;

        cartoon_random_generator(&n2);
        printf("Random number = %d\n", n2);
    }

    // ok, statement
    {
        int n3;

        n3 = 9;
        cartoon_random_generator(&n3);
        printf("Random number = %d\n", n3);
    }

    // both ok and not ok
    {
        int n4, n9;

        n9 = 9;
        //strcmp(cartoon, "XKCD") == 0 ? cartoon_random_generator(&n4) : cartoon_random_generator(&n9);
        if (strcmp(cartoon, "XKCD") == 0)
            cartoon_random_generator(&n4);
        else
            cartoon_random_generator(&n9);
        printf("Random numbers = %d, %d\n", n4, n9);
    }
}
但是规则2没有被考虑在内,我不明白为什么。运行它可以提供:

$ /opt/coccinelle/bin/spatch -sp_file cartoon_random.cocci cartoon_random.c
init_defs_builtins: /opt/coccinelle/share/coccinelle/standard.h
warning: rule3: inherited metavariable p2 not used in the -, +, or context code
HANDLING: cartoon_random.c
diff =
--- cartoon_random.c
+++ /tmp/cocci-output-7916-8df75b-cartoon_random.c
@@ -23,7 +23,6 @@ static void test(const char *cartoon)
        {
                int n1;

-               cartoon_random_generator(&n1);
                printf("Random number = %d\n", n1);
        }

@@ -40,7 +39,6 @@ static void test(const char *cartoon)
                int n3;

                n3 = 9;
-               cartoon_random_generator(&n3);
                printf("Random number = %d\n", n3);
        }

@@ -51,9 +49,7 @@ static void test(const char *cartoon)
                n9 = 9;
                //strcmp(cartoon, "XKCD") == 0 ? cartoon_random_generator(&n4) : cartoon_random_generator(&n9);
                if (strcmp(cartoon, "XKCD") == 0)
-                       cartoon_random_generator(&n4);
                else
-                       cartoon_random_generator(&n9);
                printf("Random numbers = %d, %d\n", n4, n9);
        }
 }

我是一个完全初学者在使用Coccinelle,并一直打算了解它。您提出的问题是检测未初始化变量的一个相当好的要求,这使我进行了一些研究。在做了一点研究(&从
中获得线索警告:规则3:继承的元变量p2未在-、+、或上下文代码中使用)
)之后,使您的coccinelle脚本工作的方法之一(可能还有其他/更好的方法)是将规则1和2结合起来,并在最终规则中仅对元变量使用单一继承。在这些方面:

@rule1@
position p1;
expression init_expression;
identifier n;
@@

(
int n = init_expression;
|
int n;
...
n = init_expression;
)
...
cartoon_random_generator@p1(&n)

@rule2@
position p2 != rule1.p1;
identifier n;
@@

int n;
...
* cartoon_random_generator@p2(&n)  
本例中的输出为:

$spatch -sp_file cartoon_random.cocci cartoon_random.c
init_defs_builtins: /usr/share/coccinelle/standard.h
HANDLING: cartoon_random.c
diff =
--- cartoon_random.c
+++ /tmp/cocci-output-7916-8df75b-cartoon_random.c
@@ -23,7 +23,6 @@ static void test(const char *cartoon)
        {
                int n1;

-               cartoon_random_generator(&n1);
                printf("Random number = %d\n", n1);
        }

@@ -51,9 +50,6 @@ static void test(const char *cartoon)
                n9 = 9;
                //strcmp(cartoon, "XKCD") == 0 ? cartoon_random_generator(&n4) : cartoon_random_generator(&n9);
                if (strcmp(cartoon, "XKCD") == 0)
-                       cartoon_random_generator(&n4);
                else
                        cartoon_random_generator(&n9);
                printf("Random numbers = %d, %d\n", n4, n9);
这是在FC15上运行的,从Fedora repos安装了coccinelle软件包。
希望这有帮助

Julia还提供了以下更简单的版本

@@
idexpression n;
expression E;
@@

... when != n = E
* cartoon_random_generator(&n)

更新:用idexpression替换标识符,可以更好地处理不同的块范围。

非常好。我真的很喜欢规则1现在更清楚地表达了意图。非常感谢!这将帮助我学到更多
@@
idexpression n;
expression E;
@@

... when != n = E
* cartoon_random_generator(&n)