【问题标题】:How do I check C source file for missing return error checking?如何检查 C 源文件是否缺少返回错误检查?
【发布时间】:2014-08-25 19:14:56
【问题描述】:

假设你有这样的代码:

int* a = (int*) malloc(20);
a[3]=2;
pid_t q = fork();
if(!q) {
    char *a[5];
    for (q=4; ;--q) {
        if(q<0) break;
        a[q]="q";
    }
    execve("q", a, NULL);
}
if(q) kill(q, 9);
free(a);

使用 gcc -Wallclang -Wall 构建时不会发出任何警告,使用 cppcheck --enable=all 时不会发出任何警告。

Hovewer 忽略了检查 mallocforkexecve 的错误返回值显然会导致问题。如何静态检查 C 源代码中的此类错误?

【问题讨论】:

  • 我不认为你可以。这些是典型的运行时错误,valgrind 或许可以帮助您。
  • 为什么不能?许多函数都有一个记录在案的返回值,以防出错。静态检查器可以验证在调用之后(或立即在也可用于检查器的下一个调用函数中)的返回值是否存在 if?,如果没有则显示警告。
  • 好吧,我想应该可以,但我从来没有听说过有什么工具可以做到。
  • 也许你可以自己写!
  • @Al.Sal,最简单的方法是什么?一个clang插件?

标签: c error-handling static-analysis


【解决方案1】:

如果找不到专门的解决方案,我会转向 findgrep 来搜索对 malloc 的每个调用,以及您认为对检查其返回值很重要的任何其他函数。我会一次浏览每一个,然后用眼睛快速扫描结果。

find . -type f -name '*.[ch]*' -exec grep -HnA2 'malloc' {}  \; 

如果您怀疑超过两行的尾随上下文更适合捕获返回值测试,请将传递给 grep 的 A2 增加到 A3

【讨论】:

  • 技术含量太低:1.需要人工。如果我手动检查 N 个以上的案例,我就不再专心了; 2. 没有注意到隐藏在宏后面或格式异常的东西; 3. 仅当您知道特定功能的陷阱时才有效。我希望解决方案包含已知库函数的数据库,这些函数可以捕获我个人还不知道的东西。
  • 很公平,我并不感到惊讶,但有时必须完成。
【解决方案2】:

我开发 Cppcheck

如果 Cppcheck 在 malloc 之后对每个缺失的 NULL 指针检查发出警告,它会写入误报。一些/大多数人假设/知道永远不会出现内存不足,因此 malloc 的返回值没有经过设计检查。

我相信对于某些人来说,为此设置一个检查器会很有用。如果有人想在 Cppcheck 中使用它.. 我反对将它放在 Cppcheck 本身中。我建议改为编写插件(脚本)或规则(正则表达式)。我可以将它添加到存储库中。然后那些想要这个的人可以使用那个插件/规则。

【讨论】:

  • 那么可以提取Cppcheck来理解unistd.h函数吗?
  • 是的。如果您需要此特定检查,我建议您使用规则或插件。但是也可以通过调整 cfg 文件来扩展 Cppcheck - 许多内部 Cppcheck 检查器需要了解各种功能等才能知道会发生什么。这些知识不是硬编码的,它取自用户可以调整的 xml 文件。
  • 我建议您阅读“编写规则”文章,您可以在这里下载:sourceforge.net/projects/cppcheck/files/Articles 如果您认为规则还不够,您可以编写一个插件来代替。插件更强大,你可以访问tokenlist+ast+valueflow,但是还没有编写插件的文档。
【解决方案3】:

因此,您希望根据(隐式)编码规则检查您的源代码。我假设您使用最近的 gcc 编译器进行编译...

如果源代码很大,在MELT 中编写自己的GCC 扩展可能是有意义的,MELT 是一种特定于域的语言和扩展 GCC 的插件。然而,这需要一些(数周)的工作。

【讨论】:

    猜你喜欢
    • 2013-12-06
    • 2011-08-10
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    相关资源
    最近更新 更多