首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 組合語言

Win32 API 資源管理:無需釋放的 GDI 物件與字串資源

     編輯:組合語言

前言

Win32 程式設計中,GDI 物件、核心物件、記憶體區塊等資源通常需配對釋放 (DeleteObject, CloseHandle, GlobalFree),但有幾類資源 系統自動管理,呼叫端無需 (且不應) 釋放。本文列舉這些特例並說明原因。

無需釋放的資源清單

函數/資源取得方式原因注意事項
LoadCursor載入游標資源系統快取,進程結束自動釋放不可呼叫 DestroyCursor
LoadIcon載入圖示資源系統快取,進程結束自動釋放不可呼叫 DestroyIcon (共享圖示)
LoadString載入字串資源複製到呼叫端緩衝區,非物件控制代碼緩衝區由呼叫端管理 (棧/堆)
GetStockObject取得預設 GDI 物件系統全域單例,永久存在不可呼叫 DeleteObject

詳細說明

1. LoadCursor / LoadIcon — 共享資源快取


hCursor = LoadCursor(NULL, IDC_ARROW)   ; 系統標準游標
hIcon   = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MYICON))
  • 系統維護資源快取表,相同參數重複呼叫返回同一控制代碼。
  • 進程終止時系統統一清理,呼叫 DestroyCursor/Icon 反而會破壞快取邏輯,導致其他元件使用失效控制代碼。
  • 例外:CreateIconIndirect、CopyIcon、LoadImage(LR_DEFAULTSIZE | LR_SHARED) 產生的非共享物件 必須 配對銷毀。

2. LoadString — 字串複製而非物件


char szBuf[256];
LoadString(hInstance, IDS_MYSTRING, szBuf, 256)
  • 函數將資源區字串複製到呼叫端提供的緩衝區,返回複製字元數。
  • 無控制代碼、無核心物件,自然無釋放概念。緩衝區生命週期由呼叫端控制 (區域變數/堆積/靜態)。

3. GetStockObject — 系統全域單例


hPen = GetStockObject(BLACK_PEN)
hBrush = GetStockObject(WHITE_BRUSH)
hFont = GetStockObject(SYSTEM_FONT)
  • 返回預設 GDI 物件的永久控制代碼,全系統共用單一實例。
  • 物件由系統建立於啟動期,銷毀於關機期,應用程式無權管理。
  • 呼叫 DeleteObject(hPen) 會失敗 (返回 0) 且可能破壞其他元件繪圖。

常見錯誤模式


; 錯誤:嘗試釋放共享資源
hCursor = LoadCursor(NULL, IDC_WAIT)
; ... 使用 ...
DestroyCursor(hCursor)  ; ❌ 錯誤!破壞系統快取

; 錯誤:釋放標準物件
hBrush = GetStockObject(GRAY_BRUSH)
DeleteObject(hBrush)    ; ❌ 錯誤!標準刷不可刪除

對比:必須釋放的資源

最佳實務建議

  1. 默認原則:誰建立誰釋放;LoadXxx/GetStockObject 非建立函數,不負責釋放。
  2. RAII 模式:C++ 使用智慧指標 (std::unique_ptr with custom deleter) 自動管理;組合語言建立結構化清理標籤 (cleanup:) 確保所有路徑釋放。
  3. 工具驗證:使用 GDIView、HandleEx、Application Verifier 偵測洩漏與雙重釋放。

總結

LoadCursor、LoadIcon、LoadString、GetStockObject 取得的資源屬於系統管理的共享/快取/單例類別,呼叫端無需也不可釋放。混淆「建立」與「取得」是資源洩漏與崩潰的常見根因。建立清晰的資源所有權心智模型,是穩健 Win32 程式設計的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
資源類型建立函數釋放函數
筆刷CreatePen, CreateSolidBrushDeleteObject
字型CreateFont, CreateFontIndirectDeleteObject
位圖CreateBitmap, CreateCompatibleBitmapDeleteObject
圖示/游標 (非共享)CreateIconIndirect, CreateCursorDestroyIcon, DestroyCursor
裝置內容GetDC, CreateCompatibleDCReleaseDC, DeleteDC
記憶體GlobalAlloc, HeapAlloc, VirtualAllocGlobalFree, HeapFree, VirtualFree
核心物件CreateFile, CreateThread, CreateEventCloseHandle