CString 的 ReleaseBuffer 会释放 Shell 分配的 CoTaskMemAlloc 字符串吗?
Will CString's ReleaseBuffer release Shell Allocated CoTaskMemAlloc String?
我相信,通过查看 this 文章,我可以安全地使用 CStrings 来存储某些 Windows API 函数返回的字符串结果。
例如,我可以执行以下操作(不是我的代码,来自我上面链接的文章):
//GetCurrentDirectory gets LPTSTR
CString strCurDir;
::GetCurrentDirectory(MAX_PATH, strCurDir.GetBuffer(MAX_PATH));
strCurDir.ReleaseBuffer();
GetCurrentDirectory 以"regular" 方式分配数据。我知道我也可以使用 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 的调用是否因此无效?或者这会正常工作吗?在这种情况下使用任何字符串 class 并仅使用普通 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;
}
我相信,通过查看 this 文章,我可以安全地使用 CStrings 来存储某些 Windows API 函数返回的字符串结果。
例如,我可以执行以下操作(不是我的代码,来自我上面链接的文章):
//GetCurrentDirectory gets LPTSTR
CString strCurDir;
::GetCurrentDirectory(MAX_PATH, strCurDir.GetBuffer(MAX_PATH));
strCurDir.ReleaseBuffer();
GetCurrentDirectory 以"regular" 方式分配数据。我知道我也可以使用 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 的调用是否因此无效?或者这会正常工作吗?在这种情况下使用任何字符串 class 并仅使用普通 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;
}