轉載請說明原出處,謝謝~~c++
今天下午羣友的網友讓我幫忙看一下的duilib程序的問題,程序中包含了List控件,會定時清除全部子項目而後從新添加。可是程序運行一段時間後會本身崩潰!我編譯了源碼運行後在任務管理器裏發現,程序的gdi句柄數一直增長而不減小,不到半分鐘的時候gdi句柄數竟然增長到10000個!!當時我就驚呆了,而後程序直接崩潰,如圖:函數
很明顯發生了gdi泄漏。隨後我也看了本身的仿酷狗程序,竟然也發現了gdi泄漏。當音樂項目增長到幾百個以後gdi句柄暴漲,程序崩潰。隨後進入debug模式開始調試。ui
通過3個小時的奮戰,終於發現uilib庫中有一處地方形成gdi泄漏!過程我就再也不贅述了。直接說明問題。spa
bug是uilib庫的CControlUI控件的構造函數的函數體建立了一個gdi對象:.net
CControlUI::CControlUI() : m_pManager(NULL), //省略無用代碼 { //省略無用代碼 ::ZeroMemory(&m_rcPadding, sizeof(m_rcPadding)); ::ZeroMemory(&m_rcItem, sizeof(RECT)); ::ZeroMemory(&m_rcPaint, sizeof(RECT)); ::ZeroMemory(&m_rcBorderSize, sizeof(RECT)); ::ZeroMemory(&m_tRelativePos, sizeof(TRelativePosUI)); m_hRgn = CreateRectRgn(0,0,0,0); //定義新的空的HRGN.不能初始化爲NULL }能夠看到最後一句m_hRgn = CreateRectRgn(0,0,0,0);建立了gdi對象,m_hRgn變量的說明爲:
HRGN m_hRgn; //當啓用不規則區域時,此變量保存該對象的區域這個gdi對象在 CControlUI控件的構造函數中被建立,析構函數釋放。而你們知道,CControlUI控件是全部duilib控件的基類,這就意味了每建立一個控件就會增長一個gdi對象。而偏偏是List控件,有可能會一次性添加上千條子項目,而這些子項目在程序結束時纔會被銷燬,這樣就致使程序增長上千個gdi對象,而通常程序的gdi對象都保持在50個左右,300個gdi對象已經算不少了!
我看了看和m_hRgn變量相關的代碼,發如今uilib庫中這個變量目前尚未什麼實際用途,因此我把與他相關的代碼都刪除了,使用uilib庫的朋友能夠本身刪除,也可能下載我修改好的。下載地址:點擊打開連接
debug
以上是說明了uilib庫的bug,尚未解決羣友的基於duilib庫的gdi泄漏的問題。調試他的代碼後發現duilib庫中並無gdi泄漏,最終發現是這樣的問題出在用於建立自定義控件的xml文件中:調試
1)c++調用代碼動態增長子項目到List中code
2)每一個子項目都是自定義控件,經過xml文件建立。xml
問題出在xml文件中,用xml文件動態建立控件是用duilib時的經常使用功能,而咱們千萬不要在建立自定義控件的xml文件中使用<Font>標籤,不然每次建立一個自定義控件,就會增長相應數量的font對象,而font對象是直接在CPaintManager類中增長的,一樣也是在程序結束時纔會被釋放。偶爾一兩個這樣的控件無所謂,可是若是用在List中被建立了成千上百個,gdi泄漏就太明顯!因此<Font>標籤最好統一聲明到主xml文件或者專門聲明資源的xml文件中!切記對象
2014.8.12 Redrain