MFC-User-Objects

一、用戶對象、句柄

User interface objects support only one handle per object. Processes cannot inherit or duplicate handles to user objects. Processes in one session cannot reference a user handle in another session.

There is a theoretical limit of 65,536 user handles per session. However, the maximum number of user handles that can be opened per session is usually lower, since it is affected by available memory. There is also a default per-process limit of user handles. To change this limit, set the following registry value:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\USERProcessHandleQuota

This value can be set to a number between 200 and 18,000.

理論上每個會話句柄上限爲65536,實際上由於內存有限每個回話可以使用的句柄數很少。每個進程可使用的句柄數量當然也有限制,可以通過修改註冊表改變限制值(200~18000)。

Handles to User Objects

Handles to user objects are public to all processes. That is, any process can use the user object handle, provided that the process has security access to the object.

In the following illustration, an application creates a window object. The CreateWindow function creates the window object and returns an object handle.
在這裏插入圖片描述
After the window object has been created, the application can use the window handle to display or change the window. The handle remains valid until the window object is destroyed.

在調用CreateWindow創建窗口對象操作系統將返回對象句柄,句柄從此時開始生效直到窗口對象銷燬。

In the next illustration, the application destroys the window object. The DestroyWindow function removes the window object from memory, which invalidates the window handle.

在這裏插入圖片描述

可以調用DestroyWindow 銷燬窗口並使窗口句柄無效。

二、通過註冊表修改用戶對象數量限制

//========一個demo,演示查詢註冊表鍵值,和設置
	HKEY hKEY;
	LPCTSTR strRegisKey="SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows";

	long iRtnOpenKey=(::RegOpenKeyEx(HKEY_LOCAL_MACHINE,strRegisKey,0,KEY_QUERY_VALUE|KEY_SET_VALUE|KEY_WOW64_64KEY,&hKEY));
	if(iRtnOpenKey!=ERROR_SUCCESS)
	{
		return false;//無法查詢、讀取
	}
	DWORD iKeyValue=0;
	DWORD iKeyType=REG_DWORD;
	DWORD iKeySize=sizeof(DWORD);
	long iRtnReadKey=::RegQueryValueEx(hKEY,"USERProcessHandleQuota",NULL,&iKeyType,(LPBYTE)&iKeyValue,&iKeySize);
	if(iRtnReadKey!=ERROR_SUCCESS)
	{
		::RegCloseKey(hKEY);//查詢失敗無法查詢有關注冊表信息
		return false;
	}
    else
    {c
        std::cout<<"Key Value"<<(int)iKeyValue<<std::endl;
    }

    iKeyValue = 10240;//在博文有介紹該key的值範圍200~18000
    iRtnReadKey=::RegSetValueEx(hKEY,"USERProcessHandleQuota",NULL,iKeyType,(LPBYTE)&iKeyValue,iKeySize);
    if(iRtnReadKey!=ERROR_SUCCESS)
    {
        ::RegCloseKey(hK1EY);//設置失敗
        return false;
    }
    else
    {
        ::RegCloseKey(hKEY);//設置成功
        return true;
    }

三、用任務管理器查看程序的User Object、Gdi Object

打開任務管理器,在詳細信息右擊點擊選擇列,勾選用戶對象、gdi對象。
在這裏插入圖片描述

  • 曾經碰到一次程序異常就是由於這個註冊表限制引起的,動態生成的程序窗口,一樣的代碼,一樣的使用方式,達到數量後就會在窗口初始化時報錯,拋出異常。後來發現就是這個問題,這個註冊表鍵默認值是10000,當某個進程的user Object數量要超過時後面的界面就沒法生成了,因爲沒有句柄資源可用了。當時一直在窗口初始化那查找原因,報錯也是首先在objcore.cpp這個函數,報空指針。
  • 在這裏插入圖片描述

四、參考

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章