CString 的 ReleaseBuffer 会释放 Shell 分配的 CoTaskMemAlloc 字符串吗?
Will CString's ReleaseBuffer release Shell Allocated CoTaskMemAlloc String?
我相信,通过查看本文,我可以安全地使用CStrings来存储某些Windows API函数的返回字符串结果。
例如,我可以执行以下操作(不是我的代码,来自我上面链接的文章):
//GetCurrentDirectory gets LPTSTR
CString strCurDir;
::GetCurrentDirectory(MAX_PATH, strCurDir.GetBuffer(MAX_PATH));
strCurDir.ReleaseBuffer();
GetCurrentDirectory 以"常规"方式分配数据。我知道我也可以使用 STL wstring 来做到这一点。
现在我的问题是,我可以安全地做到这一点吗?
int main()
{
CString profileRootPath;
HRESULT result = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, (PWSTR*)&profileRootPath);
wcout << profileRootPath.GetString();
profileRootPath.ReleaseBuffer();
Sleep(10000);
return 0;
}
根据SHGetKnownFolderPath的MSDN页面,SHGetKnownFolderPath输出的数据需要通过调用CoTaskMemFree来取消分配。因此,对 ReleaseBuffer 的调用是否无效?还是会正常工作?在这种情况下,使用任何字符串类并仅使用普通的 C 样式数组来保存数据,然后在数组上使用 CoTaskMemFree 不是个好主意吗?如果代码无效,最正确的方法是什么?
使用 ATL,代码片段可能像这样简单:
CComHeapPtr<WCHAR> pszPath;
HRESULT result = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, (PWSTR*) &pszPath);
CString sPath(pszPath);
wcout << sPath.GetString();
~CComHeapPtr
将执行超出范围CoTaskMemFree
,并且构造函数CString
将值视为const WCHAR*
。
没有CComHeapPtr
你可以这样做:
WCHAR* pszPath = nullptr;
HRESULT result = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, (PWSTR*) &pszPath);
CString sPath(pszPath);
CoTaskMemFree(pszPath);
wcout << sPath.GetString();
GetCurrentDirectory
只是将内存指针用于存储字符串,因此使用堆栈变量是有意义的,因为它的初始化和清理成本为零。如果你需要一个字符串,你可以从堆栈字符数组构建它 - 这消除了调用ReleaseBuffer
的必要性:
TCHAR pszPath[MAX_PATH];
GetCurrentDirectory(_countof(pszPath), pszPath);
CString sPath(pszPath);
我的问题的答案是否定的,我认为会是这样,因为CoTaskMemAlloc是一种特殊的内存分配方式。我会坚持常规的做事方式。
int main()
{
WCHAR* profileRootPath = nullptr;
HRESULT result = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, &profileRootPath);
wcout << profileRootPath;
CoTaskMemFree(profileRootPath);
Sleep(10000);
return 0;
}