带有自定义 Malloc 函数的 CppCheck

Posted

技术标签:

【中文标题】带有自定义 Malloc 函数的 CppCheck【英文标题】:CppCheck with custom Malloc functions 【发布时间】:2020-12-10 18:17:56 【问题描述】:

我正在开发一个包含大量遗留代码的代码库,我正在尝试将 CppCheck 更新到最新版本。

此代码依赖于许多具有以下签名的自定义 malloc 样式函数:

Status osMemAlloc(void** ptr, size_t numBytes);

此函数的签名意味着 CppCheck 没有推断出函数 osMemAlloc 正在为 ptr 分配内存,这意味着它在代码中标记了 nullPointer 空指针取消引用错误,例如:

SomeStruct* myPtr = NULL;

Status status = osMemAlloc((void**)& myPtr, sizeof(SomeStruct));
A
assert(status == SUCCESS_E);

  pT
myPtr->param1 = val1;    // (error) nullPointer Null pointer dereference
myPtr-> param2 = val2;   // (error) nullPointer Null pointer dereference       

我如何告诉 CppCheck 对 osMemAlloc((void**)& myPtr, sizeof(SomeStruct)) 的调用正在为 myPtr 分配内存。

将函数的签名更改为更自然的东西不是一种选择,因为代码库非常庞大且非常脆弱,没有适当的测试工具。

更多信息 我尝试使用各种宏定义(手动扩展)替换osMemAlloc() 的调用作为解决此问题的一种方法,并相信 CppCHeck 中存在一个错误,其中强制转换导致 CppCheck 错过分配给指针的内存分配.

分配的原始调用站点具有以下形式:

if (osMemAlloc((void **)&device,sizeof(DeviceInfo)) == OS_OK)

CPPCheck 很高兴将 osMemAlloc 替换为一个宏,该宏将扩展为:

if ((((*(&device)=cppcheck_HeapAlloc(sizeof(Device))) != NULL)
    ? SUCCESS_E : ERROR_E) == SUCCESS_E)

不幸的是,GCC 对该调用不满意,因为它需要强制转换为 (void**) 以匹配原始函数。如果添加了该演​​员,则代码变为:

if ((((*((void**)(&device))=cppcheck_HeapAlloc(sizeof(Device))) != NULL) 
    ? OS_OK : OS_ERROR) == OS_OK)

这会导致 CPPCheck 失败。我相信演员阵容足以导致CppCheck无法在cppcheck/lib/token.cpp中调用Token::addValue()

在 CppCheck 中失败的完整示例代码:

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>

typedef struct Device

   uint32_t param1;
   uint32_t param2;
 Device;

enum Status

   OS_OK = 0,
   OS_ERROR = 1
;


// Macro used to hide/replace OS Abstraction of Malloc in legacy code.
// The real code forwards to a function withe following signature:
// Status osMemAlloc(void** ptr, size_t sx);
#define osMemAlloc(ptr, sz) ((*(ptr)=malloc(sz)) != NULL ? OS_OK : OS_ERROR)

int main()

   Device* device1 = NULL;
   Device* device2 = NULL;

   /// This call / expansion of the macro without the casts is fine,
   if ((((*(&device1)=malloc(sizeof(Device))) != NULL) ? OS_OK : OS_ERROR) == OS_OK)
   
      device1->param1 = 10;
      device1->param2 = 20;
   

   /// Note the cast is ncessary when the real function is called for C++ 
   //if ((((*((void**)&device2)=malloc(sizeof(Device))) != NULL) ? OS_OK : OS_ERROR) == OS_OK)  
   if (osMemAlloc((void**)&device2, sizeof(Device)) == OS_OK)  
   
      device2->param1 = 10;     //  error: Null pointer dereference: device2 [nullPointer]
      device2->param2 = 20;     //  error: Null pointer dereference: device2 [nullPointer]
   
   printf("Done\n");

   free(device1);
   free(device2);

The Output from CppCheck
cppcheck.exe cppcheck-error.c
Checking cppcheck-error.c ...
cppcheck-error.c:39:7: error: Null pointer dereference: device2 [nullPointer]
      device2->param1 = 10;     //  error: Null pointer dereference: device2 [nullPointer]
      ^
cppcheck-error.c:26:22: note: Assignment 'device2=NULL', assigned value is 0
   Device* device2 = NULL;
                     ^
cppcheck-error.c:39:7: note: Null pointer dereference
      device2->param1 = 10;     //  error: Null pointer dereference: device2 [nullPointer]
      ^
cppcheck-error.c:40:7: error: Null pointer dereference: device2 [nullPointer]
      device2->param2 = 20;     //  error: Null pointer dereference: device2 [nullPointer]
      ^
cppcheck-error.c:26:22: note: Assignment 'device2=NULL', assigned value is 0
   Device* device2 = NULL;
                     ^
cppcheck-error.c:40:7: note: Null pointer dereference
      device2->param2 = 20;     //  error: Null pointer dereference: device2 [nullPointer]
      ^

【问题讨论】:

【参考方案1】:

我是一名 Cppcheck 开发人员。

我不知道内置配置选项或可能的解决方法。不知道该推荐什么。

一种技巧是将代码复制到某个临时文件并创建一个脚本 (sed/python/..) 来重写您的代码:

Status status = osMemAlloc((void**)& myPtr, sizeof(SomeStruct));


进入:

Status status = success; myPtr = malloc(sizeof(SomeStruct));

更合适的解决方案是在 Cppcheck 中添加改进。如果您有兴趣提供修复,请随时查看。在我看来,代码并不是超级复杂,没有必需的依赖项,所以如果你有一个可以编译 hello world 程序的 C++ 编译器,你也应该能够编译 Cppcheck。源码:https://github.com/danmar/cppcheck

【讨论】:

感谢您的回复 - 我相信 CPpCheck 中存在与强制转换为 (void**) 的错误。我在上面添加了更多信息。 抱歉,一开始我误解了你的意思。我已经创建了这张票:trac.cppcheck.net/ticket/10047希望你认为这看起来不错。它应该很快修复..但如果你想要一个快速的解决方案,请随时查看它。 :-) 编辑:如果你解决了,请提供一个 github pull request。

以上是关于带有自定义 Malloc 函数的 CppCheck的主要内容,如果未能解决你的问题,请参考以下文章

自定义 cppcheck 规则集

CppCheck 自定义规则不显示消息

cppcheck 是不是分析多个文件

cppcheck警告:变量未在带有初始化初始化的构造函数中实例化

Cppcheck : mismatchAllocDealloc 错误

日本程序开发式自定义的malloc/free函数-源代码(ソースコード)