SHBrowseForFolder 記憶體洩露

je_ck發表於2024-11-11

SHBrowseForFolder 函式在執行過程中會動態分配記憶體來儲存與所選資料夾相關的資訊,這些資訊以 ITEMIDLIST 結構的形式返回。而 SHGetPathFromIDList 函式只是負責從這個 ITEMIDLIST 結構中提取出路徑資訊並填充到指定的緩衝區中,但它並不會釋放 ITEMIDLIST 所佔用的記憶體。為了避免記憶體洩漏,就需要呼叫 CoTaskMemFree 函式來顯式地釋放這塊由 SHBrowseForFolder 分配的記憶體,因為這塊記憶體是透過 COM 任務分配器(CoTaskMemAlloc)分配的,所以需要使用與之對應的 CoTaskMemFree 函式來釋放。

出處:https://learn.microsoft.com/zh-cn/windows/win32/api/shlobj_core/nf-shlobj_core-shbrowseforfoldera
呼叫應用程式負責呼叫 CoTaskMemFree ,以在不再需要時釋放 SHBrowseForFolder 返回的 IDList。

一定要釋放PCIDLIST_ABSOLUTE。否則記憶體洩漏。

#include "stdafx.h"
#include <windows.h>
#include <shlobj.h>
#include <stdio.h>
#include <tchar.h>
#include <iostream>


int _tmain(int argc, _TCHAR* argv[])
{
std::wcout.imbue(std::locale("chs"));
TCHAR szPath[MAX_PATH];
BROWSEINFO bi = { 0 };
bi.lpszTitle = _T("請選擇一個資料夾");
LPITEMIDLIST pidl = SHBrowseForFolder(&bi);

if (pidl != 0)
{
if (SHGetPathFromIDList(pidl, szPath))
{
std::wcout << _T("你選擇的資料夾是: ") << szPath << std::endl;
}
else
{
std::cerr << _T("無法獲取資料夾路徑。") << std::endl;
}

// 釋放記憶體
CoTaskMemFree(pidl);

std::wcout << _T("你選擇的資料夾是: ") << szPath << std::endl;

}
else
{
std::cerr << _T("未選擇資料夾。") << std::endl;
}

return 0;
}

相關文章