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;
}
|