C++Test静态分析时,抛出”解析文件失败”异常的原因及解决办法
C++Test可以执行代码静态分析,检验代码是否符合MisraC++等规则。本文讨论了C++Test进行静态分析时候,抛出解析文件失败错误的原因,并提出绕过去的方法。
本文内容基于以下软件环境Windows 7 / Visual Studio 2010 / C++Test9.0VS插件版
时间仓促,本文文字没有认真组织,以说明清楚问题为主,希望对遇到同样问题的同行提供一些思路。
C++Test静态分析时,不是调用cl.exe完成代码解析
C++Test要分析代码,必然要先解析代码。一开始我认为C++Test是用本地编译器来完成代码解析(比如VC的cl.exe),然而实际上并不是这样。它执行静态分析的流程是:
1. vs 2010调用C++Test提供的cwc.exe
2. cwc.exe调用cl.exe,对源文件预处理。注意,仅仅是预处理。
3. cwc.exe对预处理的代码进行解析。
以下是在vs 2010中执行静态分析,系统中相关进程活动情况。尤其请注意cl.exe的命令行参数/E。根据msdn,/E的作用是:“Preprocesses C and C++ source files and copies the preprocessedfiles to the standard output device. The/E option suppressescompilation. You must resubmit the preprocessed file for compilation.”也就是说,C++Test仅仅调用cl做预处理。
另外,调用cl.exe进行预处理也是需要在用户中指定的,VC中默认是调用C++Test自身的预处理器。
VS中启动C++Test静态分析功能后,系统进程的活动情况记录表:
序号 |
Time of Day |
Process Name |
PID |
Operation |
Path |
Image Path |
1 |
37:33.4 |
devenv.exe |
11620 |
Process Create |
C:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\bin\cwc.exe |
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe |
2 |
37:33.4 |
cwc.exe |
14320 |
Process Start |
C:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\bin\cwc.exe |
|
3 |
37:33.9 |
cwc.exe |
14320 |
Process Create |
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\cl.exe |
C:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\bin\cwc.exe |
4 |
37:33.9 |
cl.exe |
5324 |
Process Start |
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\cl.exe |
|
5 |
37:36.9 |
cl.exe |
5324 |
Process Exit |
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\bin\cl.exe |
|
6 |
37:40.3 |
cwc.exe |
14320 |
Process Exit |
C:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\bin\cwc.exe |
上表中cwc.exe进程的命令行 |
"C:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\bin\cwc.exe" "--psrc=C:\Users\vigour\AppData\Local\Temp\cs_global_config35632.tmp" "--psrc=C:\Users\vigour\AppData\Local\Temp\cs_file_config35635.tmp" "--psrc=C:\Users\vigour\AppData\Local\Temp\cs_project_config35634.tmp" "--ltm=1066263b" "-Zspawn" "--report-violations-in-utf8=on" "--summary-run-temp-dir=C:\Users\vigour\AppData\Local\Temp\parasoft\globalAnalysisTemp" "--native-options-start" "-IC:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\runtime\include" "/nologo" "/Od" "/Id:\boost_1_53_0\\" "/Gm" "/EHsc" "/RTC1" "/MDd" "/DWIN32" "/D_DEBUG" "/D_CONSOLE" "/D_UNICODE" "/DUNICODE" "/GR-" "/W3" "/nologo" "/ZI" "/Gd" "/FC" "-DPARASOFT_CPPTEST" "-I." "-w" "--native-options-end" "D:\hy\codes\tools\MemoryLeaks\MemoryLeaks\MemoryLeaks.cpp" "--fileName=D:\hy\codes\tools\MemoryLeaks\MemoryLeaks\MemoryLeaks.cpp" "--compiler-cfg-file=C:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\etc\compilers\vc_10_0\cpp.psrc" "--preprocessorExecutable=cl.exe" |
上表中cl.exe进程的命令行 |
cl.exe "-IC:\Program Files (x86)\Parasoft\C++test for Visual Studio\9.0\engine\runtime\include" "/Id:\boost_1_53_0\\" /EHsc /MDd /DWIN32 /D_DEBUG /D_CONSOLE /D_UNICODE /DUNICODE /GR- -DPARASOFT_CPPTEST -I. -w -E -Tp "D:\hy\codes\tools\MemoryLeaks\MemoryLeaks\MemoryLeaks.cpp" |
C++Test静态分析的时候会错误的不能解析源文件
如上文所述,C++Test静态分析是自己解析C++代码,类似于做了一个C++的编译器。然而这个编译器并不完善,表现为,在VS 2010中能正常编译的代码,C++Test解析却会出错。这个时候,我想到的方法只能是通过PARASOFT_CPPTEST预编译指令绕过去。
以下的代码是例子。请注意其中的#ifdef PARASOFT_CPPTEST部分。
#include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/allocators/allocator.hpp> #include <boost/interprocess/containers/deque.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/containers/string.hpp> namespace ipc= boost::interprocess ; typedef ipc::managed_shared_memory SharedMemory; typedef ipc::managed_windows_shared_memory WinSharedMemory; typedef SharedMemory::segment_manager SegmentManager; typedef ipc::allocator<void, SegmentManager> VoidAllocator; typedef ipc::allocator<char, SegmentManager> CharAllocator; typedef ipc::basic_string<char, std::char_traits<char>, CharAllocator> CharString; typedef ipc::allocator<CharString, SegmentManager> CharStringAllocator; typedef ipc::vector<CharString, CharStringAllocator> CharStringVector; class EVENT_NOTIFY { public: EVENT_NOTIFY(VoidAllocator& alloc): strEventName(alloc), vctEventParas(alloc){ } // 这段代码是不需要的,但是少了它,C++Test静态检查、解析文件会失败。 #ifdef PARASOFT_CPPTEST const EVENT_NOTIFY& operator=(const EVENT_NOTIFY& src){ strEventName =src.strEventName; vctEventParas = src.vctEventParas; return *this; } #endif CharString strEventName ; CharStringVector vctEventParas ; }; int _tmain(int argc, _TCHAR* argv[]) { SegmentManager* ps = 0; VoidAllocator alloc(ps); typedef ipc::allocator<EVENT_NOTIFY, SegmentManager> EVENT_NOTIFY_Allocator; boost::interprocess::deque<EVENT_NOTIFY, EVENT_NOTIFY_Allocator> d(alloc); EVENT_NOTIFY aa(alloc); d.push_back(aa); return 0; }
|