我在QT圖形場景視圖中通過QGraphicsProxyWidget添加代理Widget(實現添加基本的QT Widget,如按鈕、復選框、日期時間控件等),當數量超過3500左右的時候,QT應用程序直接崩潰了~
提示: CreateWindowEx failed (當前程序已使用了 Window 管理器對象的系統允許的所有句柄。)
這里我是在Windows系統上進行的實驗,可見,創建WIdget的時候底層還是調用的Windows API CreateWindowEx
在Linux(Ubuntu)上進行測試,沒有發現限制問題。
QT創建Widget的時候實際上調用了Windows API CreateWindowEx,當創建的數量很多時就會造成窗口句柄不夠用。
初步分析:Windows的窗口句柄是有限制的,當消耗殆盡就會出現上述的錯誤提示,從而導致程序崩潰退出!
在Windows平台上使用GetLastError 獲取錯誤碼 1158
[1158]-當前程序已使用了 Window 管理器對象的系統允許的所有句柄。
1158 : ERROR_NO_MORE_USER_HANDLES
The current process has used all of its system allowance of handles for Window Manager objects.
意思是說你的程序已經沒有可用句柄能再分配使用了,系統分配給一個進程的可用句柄數是有限的,我猜測你的程序中打開了大量句柄,但是用過之后卻沒有記得釋放,好好檢查一下代碼吧,句柄不用了就要CloseHandle()釋放掉,不然系統的句柄資源會被你耗光的.
比如說,hProcess := OpenProcess(...);獲取一個進程句柄,當你對這個進程操作完成過后,就要CloseHandle(hProcess);
如果程序中創建很多個窗口,創建過程中會導致進程的“User Objects”數量不斷增大,會超過每個進程允許的上限值(每個進程GDI句柄上限10000,用戶句柄上限10000),you should avoid getting anywhere near it as there is also a session-wide limit that is too close for comfort to the per process limit.
關於Windows句柄數限制
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows
設置:
GDIProcessHandleQuota項設置GDI句柄數量,默認值為2710(16進制)/10000(10進制),該值的允許范圍為 256 ~ 16384 ,將其調整為大於默認的10000的值。如果您的系統配置了2G或更多內容,不妨將其設置為允許的最大值 16384(10進制);
USERProcessHandleQuota項設置用戶句柄數量,默認值同樣為2710(16進制)/10000(10進制),該值的允許范圍為 200 ~ 18000 ,將其調整為更多的數值。同樣地,對於具有2GB或更多物理內存的系統,不妨將用戶句柄數直接設置為上限 18000(10進制);
感覺設置了沒啥作用,多出了那一點句柄數起不了什么作用。
親自試了試,確實沒啥大作用!