- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我使用下面的代码通过 SHGetKnowFolderPath()
获取 ProgramData 路径。
你能告诉我将它与 CString
一起使用是否正确吗?如果不是,使用 SHGetKnownFolderPath()
获取 ProgramData 路径的最佳解决方案是什么?
我使用了下面的 2 个示例并且都有效,但我不确定它们是否正确。
CString szProgramDataPath;
szProgramDataPath.GetBuffer(MAX_PATH);
if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, (PWSTR*)&szProgramDataPath)))
{
cout << _T("Failed, error is: ") << GetLastError();
}
或者:
CString szProgramDataPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, (PWSTR*)&szProgramDataPath)))
{
cout << _T("Failed, error is: ") << GetLastError();
}
最佳答案
这两种方法都不正确。
SHGetKnownFolderPath()
返回指向新分配的字符串的指针,您必须在使用完后使用 CoTaskMemFree()
释放它。
两个代码示例都试图使用operator&
来直接访问CString
指向其字符数据的内部指针,希望CString
将取得 SHGetKnownFolderPath()
返回的指针的所有权。
这是错误且非常危险的!出于几个原因...
您假设该内部指针的地址与CString
对象本身的地址相同。 CString
不会覆盖 operator&
以返回其内部缓冲区指针的地址,就像您假设那样。
即使如此,第一个代码示例仍然存在问题,因为它存在内存泄漏。您正在使用 GetBuffer()
预先分配字符缓冲区(之后不调用 ReleaseBuffer()
)。 SHGetKnownFolderPath()
在重新分配指向返回内存块的指针之前不会释放该缓冲区,因此您最终会泄漏较早的内存块。
并且您假设 CString
的析构函数使用CoTaskMemFree()
(或兼容函数)来释放其内部字符缓冲区。这是不安全的假设。
并且您假设 CString
的内部字符缓冲区的内存布局与 SHGetKnownFolderPath() 返回的内存块的内存布局兼容
。实际上并非如此,因为 CString
为其字符数据(除其他外)实现了一个引用计数器。您认为该计数器存储在哪里?对,在字符缓冲区本身内部!由于 SHGetKnownFolderPath()
不返回与 CString
的数据格式兼容的内存缓冲区,您将破坏您的 CString
数据并且当它稍后尝试访问内存中不存在的东西时会导致问题。参见 CString In A Nutshell有关“CString 的内部细节”的更多信息。
简而言之,CString
并非旨在按照您尝试的方式使用。您正在做出一些非常危险的假设,从而在您的代码中导致未定义的行为!
您不能直接访问 CString
的内部缓冲区指针以将其重新分配给不同的地址。 正确的解决方案看起来更像这样:
CString szProgramDataPath;
LPWSTR pProgramDataPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, &pProgramDataPath)))
{
// DON'T use _T() here! std::cout expects char* strings only...
cout << "Failed, error is: " << GetLastError();
}
else
{
szProgramDataPath = pProgramDataPath;
CoTaskMemFree(pProgramDataPath);
}
如果你想自动销毁返回的内存块,尤其是当 CString
分配失败并出现异常时,请使用智能指针,如 std::unique_ptr
(参见 std::unique_ptr, deleters and the Win32 API ),例如:
CString szProgramDataPath;
LPWSTR pProgramDataPath;
if (FAILED(SHGetKnownFolderPath(FOLDERID_ProgramData, 0, NULL, &pProgramDataPath)))
{
// DON'T use _T() here! std::cout expects char* strings only...
cout << "Failed, error is: " << GetLastError();
}
else
{
std::unique_ptr<WCHAR, decltype(CoTaskMemFree)> deleter(pProgramDataPath, &CoTaskMemFree);
szProgramDataPath = pProgramDataPath;
}
关于c++ - 如何使用 SHGetKnownFolderPath API 中的 CString 对象获取程序数据路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42841832/
给定 CString buffer = ""; Cstring value = "blah"; buffer.Format ("%s %s", value, value.GetBuffer()); 这
我有这个函数可以将事件(每个事件都是一个 cstring)添加到事件数组中: bool vendor::addEvent(const char * event) { if (eventsSiz
我可以在 CString::Format 中使用 CString 吗,如下所示: CString text = _T("text"); CString format; format.Format(_T
我正在 Ubuntu 16.04 上使用 ROS 和 C++ 开展一个小组项目。一切正常,直到两周前我收到此错误突然的消息: In file included from /usr/include/c+
我有一个将 CString 作为参数之一的函数,我查看了代码库,发现很多地方都使用 const CString& 作为参数。 所以我想知道使用 CString 与 const CString& 之间是
我有两个列表和一个名字要查找。如果要查找的名称不在第一个列表中,那么它可能在格式略有不同的第二个列表中。给出了两种格式之间的转换函数。 std::map* convertedNames; BOOL C
我需要为我的对象计算签名(一种哈希)。计算需要许多每个字符的操作,因此为了加快此过程,我的代码对 CString 进行操作,然后将计算的 CString 转换为最终的 NSString。 stub 代
PVS 工作室发现了一个我正在调查的潜在缺陷;警告 V623 http://www.viva64.com/en/d/0240/ 但是,没有足够的解释来理解为什么要制作临时拷贝。如果 CString::
假设我有以下字符串 char array[1000]; 我如何将它转换为 NSString,反之亦然。 谢谢。 最佳答案 Apple 的开发者引用有一个 good article关于这个问题。基本上,
一些简单的代码在我一直使用的 sdk 中开始出现故障,而且它显然已经正常工作了很长时间,事实上我几乎可以肯定我已经编译了部分代码并且他们有工作,但最近失败了。 在调试器中确认值的示例: void So
我正在尝试这样做: #include CHAR Filename; // [sp+26Ch] [bp-110h]@1 char v31; // [sp+36Ch] [bp-10h]@1 int v3
我知道字符数组不同于 cstring,因为在 cstring 中包含后缀\0 标记值。然而,我也明白,在 cstring、字符数组或任何其他类型的数组的情况下,程序中的数组标识符是指向数组的指针。所以
我在将 unsigned char 转换为 CString 以及将转换后的 CString 结果转换为 unsigned char 时遇到问题。 首先,我尝试使用 CString.append();。
我正在使用一个 Windows 应用程序来解析某些二进制文件。应用程序每次在某个位置都会崩溃(读取访问冲突)。 我正在尝试找出崩溃的根本原因。 (f74.fac): Access violation
需要使用下面的 LogMethod() 来记录 buf 的内容问题是LogMethos 只接受“Const CString&” char buf[1024]; strcpy(buf, cErrorMs
假设我有一个文件。我将所有字节读入一个无符号字符缓冲区。从那里我试图在不知道它的长度的情况下读取一个 c 字符串(空终止)。 我尝试了以下方法: char* Stream::ReadCString()
我在使用数组时遇到问题。我收到以下错误 In function ‘int main(int, const char**)’: 75: error: cannot convert ‘char*’ to
我一直在尝试执行从包含十六进制字符串的 CString 到字节数组的转换,并且一直在 至今未成功。我查看了论坛,到目前为止似乎都没有帮助。有没有一个功能只有几个 执行此转换的代码行数? 我的代码: B
我有两个 CString s1 和 CString s2。我需要在 s1 中找到最后一个条目 s2。我可以在 CString 中找到任何方法,就像在 C# LastIndexOf 中一样。我在 C++
我想将丰富的编辑控件中的整个文本作为 CString 获取,例如 GetDlgItemText,但这是针对对话框的。我能从我的研究中找到的最接近的东西是: GetTextRange并使用 GetTex
我是一名优秀的程序员,十分优秀!