cppcheck - 带有自定义 Malloc 函数的 CppCheck
问题描述
我正在开发一个包含大量遗留代码的代码库,并且我正在尝试将 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 无法调用Token::addValue()
cppcheck/lib/token.cpp
在 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]
^
解决方案
我是一名 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
推荐阅读
- ampl - 在 AMPL 中,如何引用部分结果,并在多个地方使用它们
- docker - 拉 nanoserver:1903 时,“清单列表条目中没有匹配的清单”
- outlook-web-addins - 在应用商店上传清单文件时出现“remoteurl”错误
- javascript - 从节点js中的缓冲区检测文件类型?
- javascript - 解释在 Javascript ES6 中调用对象方法的函数中“this”的使用
- sql - SQL 仅替换路径的一部分
- regex - 过滤掉具有 3 个或更多子文件夹的行
- android - 如何将两个不同的 Firebase 帐户用户带到不同的活动中?
- java - apache tomcat 服务器总是运行一个程序的问题,它显示端口 8080 已经被使用..?
- java - Maven surefire 插件默认策略来运行测试