那么在Windows下有什么好的內(nèi)存泄漏檢測(cè)工具呢?微軟提供Visual Studio開發(fā)工具本身沒有什么太好的內(nèi)存泄漏檢測(cè)功能,我們可以使用第三方工具Visual Leak Detector(以下簡(jiǎn)稱vld)。
vld工具是VC++環(huán)境下一款小巧易用、免費(fèi)開源的內(nèi)存泄漏檢測(cè)工具,vld可以顯示導(dǎo)致內(nèi)存泄漏的完整內(nèi)存分配調(diào)用堆棧。vld的檢測(cè)報(bào)告能夠?qū)γ總€(gè)內(nèi)存泄漏點(diǎn)提供完整的堆棧跟蹤,并且包含其源文件及行號(hào)信息。
安裝過程是,先在到地址http://vld.codeplex.com/下載vld安裝文件,然后進(jìn)行安裝,安裝過程中需要安裝程序會(huì)配置環(huán)境變量。我們需要記住安裝目錄。
安裝完成后打開要檢測(cè)的Visual Studio工程,我們需要在工程中配置:vld頭文件目錄和vld庫(kù)目錄。
選中游戲工程,打開菜單“項(xiàng)目”→ “屬性”彈出工程屬性對(duì)話框,如圖所示,選擇“配置屬性”→“VC++目錄” →“常規(guī)”,在右邊的“包含目錄”中添加C:/Program Files (x86)/Visual Leak Detector/include,其中C:/Program Files (x86)/Visual Leak Detector是我的vld安裝目錄。“庫(kù)目錄”中添加C:/Program Files (x86)/Visual Leak Detector/lib/Win32,注意配置目之間需要用分號(hào)分隔開。
配置完成之后點(diǎn)擊確定按鈕關(guān)閉對(duì)話框,然后我們需要在程序代碼中引入頭文件#include <vld.h>,但是這個(gè)頭文件在哪里引入比較好?如果是普通的一個(gè)VC++工程在哪里引入都無所謂,但是Cocos2d-x的工程就不同了,我們需要考慮跨平臺(tái),#include <vld.h>代碼不宜添加到Classes目錄下的h或cpp文件中,這個(gè)目錄下的文件是要在其它平臺(tái)編譯運(yùn)行的,而#include <vld.h>只是在Windrows平臺(tái)才有效。我們可以在Win32目錄(見圖)下的main.cpp或main.h文件引入頭文件。這些文件是與Win32平臺(tái)有關(guān)的,不同平臺(tái)移植的時(shí)候不需要。
如果在main.cpp中引入代碼如下:
#include "main.h" #include "AppDelegate.h" #include "cocos2d.h" #include <vld.h> USING_NS_CC; int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // create the application instance AppDelegate app; return Application::getInstance()->run(); }
引入之后,就測(cè)試一下了,我們來人為制造一個(gè)內(nèi)存泄漏,與20.1.1一節(jié)一樣在HelloWorldScene.cpp中修改代碼:
bool HelloWorld::init() { if ( !Layer::init() ) { return false; } __String *s = new __String(); log("%s",s->getCString()); … … return true; }
運(yùn)行工程,需要注意的是在程序運(yùn)行過程中vld是沒有堆棧輸出的,但是日志會(huì)有輸出vld的安裝信息,日志信息如下:
Visual Leak Detector Version 2.4RC2 installed.
Ready for GLSL
Ready for OpenGL 2.0
… …
從日志中可以看到vld是否安裝成功,以及安裝的版本。要想看到vld檢測(cè)報(bào)告需要退出程序后,才會(huì)在日志中輸出信息。使用Cocos2d-x會(huì)輸出很多日志信息,信息如下:
---------- Block 526166 at 0x0821FA80: 84 bytes ---------- Leak Hash: 0x780B2033, Count: 1, Total 84 bytes Call Stack (TID 4660):... ...---------- Block 526214 at 0x08224378: 8 bytes ---------- Leak Hash: 0xE1DC1852, Count: 1, Total 8 bytes Call Stack (TID 4660):... ... Data: 63 6F 63 6F 73 32 64 20 61 75 74 6F 72 65 6C 65 cocos2d. autorele 61 73 65 20 70 6F 6F 6C 00 CD CD CD CD CD CD CD ase.pool ........Visual Leak Detector detected 33 memory leaks (2892 bytes).Largest number used: 3204961 bytes.Total allocations: 69022415 bytes.Visual Leak Detector is now exiting.
其中一個(gè)Block表示一個(gè)內(nèi)存泄漏點(diǎn),在眾多Block如果能夠找到關(guān)于我們自己類的日志信息呢?我們可以查找關(guān)鍵字“helloworldscene.cpp”,這就可以定位到HelloWorld場(chǎng)景中的內(nèi)存泄漏的Block了,我們找到如下日志信息:
---------- Block 1153 at 0x01533C70: 48 bytes ---------- Leak Hash: 0x5545A5ED, Count: 1, Total 48 bytes Call Stack (TID 2088): f:/dd/vctools/crt_bld/self_x86/crt/src/new.cpp (57): MSVCR110D.dll!operator new d:/helloworld/classes/helloworldscene.cpp (33): HelloWorld.exe!HelloWorld::init + 0x7 bytes d:/helloworld/classes/helloworldscene.h (37): HelloWorld.exe!HelloWorld::create + 0xB1 bytes d:/helloworld/classes/helloworldscene.cpp (12): HelloWorld.exe!HelloWorld::createScene + 0x5 bytes d:/helloworld/classes/appdelegate.cpp (30): HelloWorld.exe!AppDelegate::applicationDidFinishLaunching + 0x5 bytes d:/helloworld/cocos2d/cocos/2d/platform/win32/ccapplication.cpp (74): HelloWorld.exe!cocos2d::Application::run + 0xF bytes d:/helloworld/proj.win32/main.cpp (19): HelloWorld.exe!wWinMain + 0xC bytes f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c (528): HelloWorld.exe!__tmainCRTStartup + 0x15 bytes f:/dd/vctools/crt_bld/self_x86/crt/src/crtexe.c (377): HelloWorld.exe!wWinMainCRTStartup 0x7563850D (File and line number not available): KERNEL32.DLL!BaseThreadInitThunk + 0xE bytes 0x77B7BF39 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x85 bytes 0x77B7BF0C (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x58 bytes Data: 1C 34 07 01 01 00 00 00 27 00 00 00 00 00 00 00 .4...... '....... 2C 34 07 01 A0 77 01 03 00 CD CD CD CD CD CD CD ,4...w.. ........ CD CD CD CD CD CD CD CD 00 00 00 00 0F 00 00 00 ........ ........
從這個(gè)日志中能看到內(nèi)存泄漏點(diǎn),從日志的堆棧中找到我們自己編寫的類,點(diǎn)擊那一行打開代碼窗口,定位內(nèi)存泄漏點(diǎn)代碼,如圖所示。
定位內(nèi)存泄漏點(diǎn)
找到哪一個(gè)有可能有內(nèi)存泄漏,解決就不是問題了。
以上所述就是本文的全部?jī)?nèi)容了,希望大家能夠喜歡。
新聞熱點(diǎn)
疑難解答
圖片精選