在最近的一次bug搜索中,我发现了一个返回指向临时变量成员的指针的问题.违规(简化)代码是:
struct S {
S(int i) : i(i) {}
int i;
int* ptr() { return &i; }
};
int* fun(int i) { return S(i).ptr(); } // temporary S dies but pointer lives on
int main() {
int* p = fun(1);
return *p; // undefined
}
Run Code Online (Sandbox Code Playgroud)
怎么预防这个?海湾合作委员会和铿锵有-Waddress-of-temporary,-Wreturn-stack-address但他们似乎因为ptr()肮脏的行为充当中间人而松散.它们仅在直接获取指针时触发:
int* fun(int i) { return &S(i).i; } // rightly fails to compile
Run Code Online (Sandbox Code Playgroud)
我的项目还将cppcheck整合到持续集成中,但它也无法获取(在这里提出).
哪种静态分析工具可以防止这类错误?
编辑:GCC确实从版本6.1.0开始接收-Wreturn-local-addr并且(令人惊讶地)-O2开启.
在代码审查期间,我找到了这样的源代码:
void f_odd(std::string &className, std::string &testName)
{
if (className.find("::") != std::string::npos)
{
testName = className.substr(className.find("::") + 2);
(void)className.erase(className.find("::"), std::string::npos);
}
}
Run Code Online (Sandbox Code Playgroud)
在这个函数中,std :: string :: find()被调用三次,具有相同的模式(这里是"::").
这个代码当然可以重构为
void f(std::string &className, std::string &testName)
{
const size_t endOfClassNamePos = className.find("::");
if (endOfClassNamePos != std::string::npos)
{
testName = className.substr(endOfClassNamePos + 2);
(void)className.erase(endOfClassNamePos, std::string::npos);
}
}
Run Code Online (Sandbox Code Playgroud)
find只被调用一次.
题
有人知道检测这种模式的策略吗?我有一个巨大的代码库,我打算发现这种模式.我计划使用Windows或Linux环境.
潜在的策略
没有Go
更新1
我决定从潜在的策略开始1).我打算让cppcheck适应这个问题.
Cppcheck提供了基于PCRE正则表达式编写自定义规则的可能性.为此,必须使用启用的PCRE支持编译cppcheck.由于当前测试环境是基于Linux的,因此可以使用以下命令下载最新版本的cppcheck:
git clone https://github.com/danmar/cppcheck.git && cd cppcheck
之后,编译并安装该工具,如下所示:
sudo make install HAVE_RULES=yes
现在基本工具设置完成了.为了开发一个cppcheck规则,我准备了一个简单的测试用例(file:test.cpp),类似于本文第一部分中的示例代码.此文件包含三个功能和cppcheck规则应在发出警告f_odd …
我发现--suppress=unmatchedSuppression仅抑制 cppcheck 选项中不匹配的抑制类型,但不抑制不匹配的内联抑制。
这是预期的行为吗?
测试.c
第4行是错误的。应该予以警告arrayIndexOutOfBounds
7号线还可以。不应该被警告arrayIndexOutOfBounds
我cppcheck-suppress对两条线都有内联。
1 void f() {
2 char arr[5];
3 // cppcheck-suppress arrayIndexOutOfBounds
4 arr[10] = 0;
5
6 // cppcheck-suppress arrayIndexOutOfBounds
7 const char ok[] = "this line is ok";
8 }
Run Code Online (Sandbox Code Playgroud)
情况1
Suppress cstyleCast,它在代码中不存在。
cppcheck --inline-suppr --force --enable=all
--xml-version=2 --suppress=cstyleCast test.c
2>cppcheckresults.xml
Run Code Online (Sandbox Code Playgroud)
我收到警告(以及其他不相关的警告)
unmatchedSuppression: arrayIndexOutOfBounds在test.c line 7(如预期)
unmatchedSuppression: cstyleCast在* line 0(如预期)
情况2
与情况 1 相同,但有附加--suppress=unmatchedSuppression选项
cppcheck --inline-suppr …Run Code Online (Sandbox Code Playgroud) 最近cppcheck在一些C代码中引发了一个错误,它具有以下结构:
((void)(value_prev = value), value = new_value())
Run Code Online (Sandbox Code Playgroud)
在大多数情况下,这可以拆分为2行,但是在某些情况下,这在单个语句中很有用.
在实践中,我发现这适用于流行的编译器(GCC/Clang/MSVC),它们不会发出任何警告(即使警告级别设置为最高).
示例代码:
#include <stdio.h>
int get_next(int i);
int main() {
int i = 0, i_prev = 10;
do {
printf("%d\n", i);
} while ((void)(i_prev = i),
(i = get_next(i)) != 10);
}
Run Code Online (Sandbox Code Playgroud)
CppCheck 1.73 (撰写本文时的最新版本)给出了以下代码的错误:
(error) Expression '(void)(i_prev=i),(i=get_next(i))!=10'
depends on order of evaluation of side effects`
Run Code Online (Sandbox Code Playgroud)
虽然代码可以更改为安静警告,但订单是否真的未定义?
在调试会话期间,我发现snprintf在使用avr-gcc编译代码时无法按预期工作.示例代码应该简单地将浮点值3999.9f转换为其字符表示形式.
这是一个最小的测试用例:
int TestSnprintf(void)
{
const float inputValue = 3999.9f;
/* Print with a fixed width of 6 characters (5 numbers and 1 dot).
The buffer must have a length of 7, because snprintf appends a '\0' at the end. */
char buf[7U] = {0, 0, 0, 0, 0, 0, 0};
const uint8_t bufferSize = 7U;
if(6 != snprintf(buf, bufferSize, "%06.1f", inputValue))
{
return -1;
}
if( buf[0] != '3'
|| buf[1] != '9'
|| buf[2] …Run Code Online (Sandbox Code Playgroud) 工具:SonarQube Server 6.0,Sonar Scanner 3.0.3,Jenkins在Linux Build Slave上运行,具有管道格式,CppuTest,gcovr,Bitbucket,git,JDK 8
问题:声纳服务器上的Coverage测量值莫名显示0.0%覆盖率,单位测试值为非零值(如下所示).使用可访问覆盖率报告的路径sonar.cxx.coverage.reportPath=.CppuTest使用-ojunit标志,gcov生成.gcna文件,使用转换为单一格式gcovr.

我已手动打开coverage-report.xml,它似乎是正确的格式(代码段):
<package branch-rate="0.0" complexity="0.0" line-rate="1.0" name="path > to unit test object file in class notation">
<classes>
<class branch-rate="0.0" complexity="0.0" filename="path to > source file" line-rate="1.0" name="nameOfSourceFile_cpp">
<lines>
<line branch="false" hits="104" number="97"/>
<line branch="false" hits="104" number="101"/>
<line branch="false" hits="104" number="103"/>
<line branch="false" hits="1" number="85"/>
<line branch="false" hits="1" number="88"/>
<line branch="false" hits="104" number="95"/>
</lines>
</class>
</classes>
</package>
Run Code Online (Sandbox Code Playgroud)
Bitbucket Pull Request上的UT Coverage字段也显示0%.我确信这个数字应该是非零的.SonarQube的所有其他方面都在工作,包括查看CppCheck.以前有人见过这样的事吗?
我计划发布和部署一个用C++和wxWidgets编写的应用程序.wxWidgets-library既可用作dll,也可用作静态库.因此,我可以选择将应用程序部署为动态构建应用程序或静态构建.
目前,我更喜欢静态构建选项,因为:
题
我错过了非常重要的事情吗?
cppcheck 新手。无法弄清楚如何解决此问题(cppcheck 警告)。任何帮助,将不胜感激。
if (!call_initialized)
{ char id1[16];
char id1[16];
char* dummy_char_ptr = inet_ntoa(*((in_addr*)&source_ip));
std::strncpy(id1, dummy_char_ptr, 16);
dummy_char_ptr=inet_ntoa(*((in_addr*)&destination_ip));
std::strncpy(id2, dummy_char_ptr, 16);
dummy_char_ptr=NULL;
std::cerr << id1 << " -----> " << id2 << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误(警告) - 调用 strncpy() 后,缓冲区“id2”可能不会以零结尾。
这个
cppcheck --enable=style --inconclusive --check-config --xml --xml-version=2 -v -I.. -I../mocks -I../gmock -I../gtest -DUNIT_TEST ../src
Run Code Online (Sandbox Code Playgroud)
结果
<?xml version="1.0" encoding="UTF-8"?>
<results version="2">
<cppcheck version="1.52"/>
<errors>
Checking ../src/AppMain.cpp...
</errors>
</results>
Run Code Online (Sandbox Code Playgroud)
显然,我做错了-但是呢?
顺便说一句,我确定代码有问题,但是可以肯定的是,我将这两行粘贴到了其中
char a[10];
a[10] = 0;
Run Code Online (Sandbox Code Playgroud)
而且没有报告超出范围引用