allegro設置內存分配器的一個坑

        看過《遊戲引擎架構》後我開始對內存的分配問題關注,一直想用內存分配器來管理遊戲的內存。前兩天發現了有許多第三方內存分配器可以用。最後挑中了nedmalloc,這個庫也是ogre所使用的,測試了一下,確實比VS的malloc/free要快不少。

    通過寫幾個簡單的函數就可以代替allegro內存分配器,十分方便,又順便給box2d也換了。

        allegro通過調用al_set_memory_interface()來替換內存分配器。然後我把這個函數放到了al_init()後面。一運行,發現很正常,不錯。點擊窗口的關閉按鈕,然後報錯了!我就猜想是不是放的位置不對。在設置分配器之前調用了al_init(),那就說明allegro初始化的時候申請的內存用的分配器還是默認的分配器,關閉的時候卸載這些初始化的數據缺用的是nedmalloc的free,這樣肯定就報錯了。於是我把al_set_memory_interface()放到了al_init()之前。再運行,關閉。完全正常!到這裏我以爲事情就結束了。

        後來在寫了若干代碼之後發現上面那個關閉時報錯的問題又出現了!於是開始找問題,註釋了幾乎所有代碼,問題依舊。最後又單步調試,發現報錯是在main()返回之後出現的,才意識到,這個問題出現在靜態變量上,接着單步調試,發現問題出在一個String類的身上。這個類封裝了allegro的字符串操作函數。(這個類所屬的庫用c++11封裝了allegro所有的對象及其操作,官方也推薦過鏈接

        這時突然纔想起來我在一個cpp文件裏定義了一個文件內的局部變量,類型正是這個String。這是個靜態變量,也就是說它初始化的時候main還沒調用,卸載的時候也在main()返回之後了。在我這個程序裏就是用默認的malloc  new的它,但最後卻用nedfree delete的它,這就出問題了。爲了解決這個問題,我在main()返回之前再一次調用al_set_memory_interface()。然後運行,又報錯!這次是al_uninstall_system()出錯了。

        我意識到,這是allegro的初始化和卸載的配對出了問題。我原來一直沒有用過al_uninstall_system()這個函數,因爲原來查資料說是allegro會自動調用這個函數。之後就是查手冊,看源碼,終於搞懂了。al_init()其實是個宏,用來代替al_install_system(),用al_init()的話會把al_uninstall_system()註冊爲main()結束後調用的函數(atexit)。所以就不能再用al_init()來初始化了,然後再手動uninstall。

        整理一下思路:就是在al_install_system()設置內存分配器,在al_uninstall_system()後設置回默認的分配器。

下面是代碼:

int main()
{
	al_set_nedmalloc_memory_interface();
	if (!al_install_system(ALLEGRO_VERSION_INT, 0))
	{
		return 1;
	}

	...

	al_uninstall_system();
	al_set_memory_interface(0);
	return 0;
}

        以後要用哪個函數的時候,最好還是先看下它的說明。在這個問題之前我都不知道al_install_system()的存在。


發佈了46 篇原創文章 · 獲贊 7 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章