CLANG++ 3.3静态分析仪,如何摆脱误报
clang++ 3.3 static analyser, how to get rid of a false positive?
我一直在我的各种项目上运行clang 3.3
的静态分析器。除了一些是我自己的错的问题(这是意料之中的,否则我会非常悲伤和非常自鸣得意),除了以下关于std::function
的移动构造函数的问题是一个误报。
在进一步讨论之前,这里有一个简单的测试用例:
int main() {
std::function<void ()> f1;
std::function<void ()> f2 = std::move(f1);
}
通过clang++ -std=c++11 --analyze -Xanalyzer -analyzer-output=text foo.cpp
运行它(它使用 GCC 的 libstdc++
- 即 4.8.1 版本 - 而不是 clang
的 libc++
),你会得到以下跟踪:
In file included from foo.cpp:1:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/iostream:39:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:38:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ios:40:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/char_traits.h:39:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_algobase.h:64:
In file included from /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/stl_pair.h:59:
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/move.h:175:7: warning: Assigned value is garbage or undefined
_Tp __tmp = _GLIBCXX_MOVE(__a);
^~~~~~~~~ ~~~~~~~~~~~~~~~~~~
foo.cpp:30:31: note: Calling move constructor for 'function'
std::function<void ()> f2 = std::move(f1);
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2232:2: note: Calling 'function::swap'
__x.swap(*this);
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/functional:2359:2: note: Calling 'swap'
std::swap(_M_invoker, __x._M_invoker);
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/move.h:175:19: note: Calling 'move'
_Tp __tmp = _GLIBCXX_MOVE(__a);
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/move.h:142:30: note: expanded from macro '_GLIBCXX_MOVE'
#define _GLIBCXX_MOVE(__val) std::move(__val)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/move.h:175:19: note: Returning from 'move'
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/move.h:142:30: note: expanded from macro '_GLIBCXX_MOVE'
#define _GLIBCXX_MOVE(__val) std::move(__val)
^
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/bits/move.h:175:7: note: Assigned value is garbage or undefined
_Tp __tmp = _GLIBCXX_MOVE(__a);
^
1 warning generated.
如您所见,移动构造函数std::function(std::function&&)
是按照swap
实现的。整个操作的步骤是(如果我们相信clang
):
-
f1
结构正确 -
f2
尚未构建,因此包含垃圾 -
f1
被搬进了f2
,但实际上它真的是一个swap
-
f2
现在包含旧f1
,但f1
包含旧f2
,即垃圾 - 在某些时候,包含垃圾的
f1
被破坏了......那怎么办呢?
理论说,这是非常糟糕的。在实践中,查看实现,似乎std::function
私下继承自_Function_base
,后者负责初始化所有重要内容(即。 _M_manager
) 为 null,因此clang
关于_M_invoker
的警告毫无意义。
以防万一有人怀疑,移动对象应该使其处于不确定状态,您只能分配给它或破坏它。GCC 的 function
实现正是这样做的:就资源管理而言,只有_M_manager
是重要的,其余的(包括_M_invoker
)只是"方便"的指针。
我在GCC的function
实施中挖掘了足够多的东西,对clang
诊断的误报状态完全毫无疑问。但是,由于我的代码中有数百个地方发生这种情况,因此至少可以说,浏览静态分析器的结果非常痛苦。
我如何指示clang
不要报告此问题?
同样,如果您错过了它,我将clang 3.3
与GCC的libstdc++ 4.8.1
一起使用。
注意:如果您正在运行clang 3.4
构建,并且它没有触发此误报,请告诉我。就我所尝试的而言,我还不能让 3.4 在我的系统上运行(Debian Jessie),但如果它解决了这个问题,我会更加努力。
这可能对你来说很有趣:分析仪的未来发展方向
基本上,您目前只能禁用每个TU或使用的某些检查器
#ifndef __clang_analyzer__
...
#endif
如果你真的需要。但当然应该报告实际的误报。
- 函数何时会在c++中包含stack_Unwind_Resume调用
- Python中的for循环与C++有何不同
- 尝试摆脱任何堆内存分配
- 如何摆脱C ++中的分段错误错误?
- 在 c++ 中使用 vtd-xml 时,如何摆脱 EOFException?
- 如何摆脱为条件编译定义预处理器宏的需要?
- 在C++中释放内存期间,迭代器与指针有何不同
- GTK:完全摆脱系统主题/CSS
- 我该怎么做才能摆脱使用命名空间时的语法错误?
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- transform_reduce & 摆脱 for 循环
- 如何摆脱算术溢出
- 如何摆脱错误c2061;语法错误 cout?
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- 如何摆脱这个做同时循环?
- 类中的 C++ int 被设置为值,似乎不知从何而来
- -fvisibility-inline-hidden 与 gcc 中的 -fvisibility=hidden 有何不同
- 如何摆脱导入的 make 项目中的 Eclipse 索引器"Type std::... could not be resolved"错误
- 我必须构建才能摆脱 Eclipse 中的错误吗?
- 如何摆脱C++中的枚举不匹配错误?