CString的ReleaseBuffer会发布Shell Allocated CoTaskMemAlloc String吗?

时间:2016-02-25 20:42:58

标签: c++ winapi mfc com

我相信,通过查看this文章,我可以安全地使用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是不是一个好主意?如果代码无效,那么最正确的方法是什么?

2 个答案:

答案 0 :(得分:2)

使用ATL,代码片段可能非常简单:

CComHeapPtr<WCHAR> pszPath;
HRESULT result = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, (PWSTR*) &pszPath);
CString sPath(pszPath);
wcout << sPath.GetString();

~CComHeapPtrCoTaskMemFree超出范围,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);

答案 1 :(得分:0)

我的问题的答案完全没有,我认为这是,因为CoTaskMemAlloc是一种分配内存的特殊方式。我只是坚持常规做事。

int main()
{
    WCHAR* profileRootPath = nullptr;
    HRESULT result = SHGetKnownFolderPath(FOLDERID_Profile, 0, nullptr, &profileRootPath);
    wcout << profileRootPath;
    CoTaskMemFree(profileRootPath);
    Sleep(10000);
    return 0;
}