gpt4 book ai didi

c++ - 跨 DLL 边界的安全字符串复制

转载 作者:太空狗 更新时间:2023-10-29 22:58:43 25 4
gpt4 key购买 nike

我正在尝试制作一个公开特定 API 的 DLL,因此想要实现一种安全的方式来跨 DLL 边界复制字符串。 DLL 实现非常简单 - 所有返回字符串值的函数都有两个参数 - char*size_t&。如果大小足够大,我将 memcpy 字符串的内容从 DLL 中传递给给定的指针,将大小设置为实际大小并返回成功的返回代码。如果不是,我将大小设置为应有的大小并返回错误代码。 DLL 端非常简单。

现在更复杂的是——如何制作一个漂亮的模板函数,它给出一个指向 DLL 中某个函数的指针,将执行所有正确的操作来填充 std::string 的实例。这就是我得出的结论:

template<typename I>
CErrorCode GetStringValue(const I& Instance, CErrorCode(I::*pMethod)(char*, size_t&) const, std::string& sValue)
{
std::string sTemporaryValue;
size_t nValueLength = sTemporaryValue.capacity();
sTemporaryValue.resize(nValueLength);
do
{
auto eErrorCode = (Instance.*pMethod)(const_cast<char*>(sTemporaryValue.c_str()), nValueLength);
if (eErrorCode == CErrorCode::BufferTooSmall)
{
sTemporaryValue.resize(nValueLength);
}
else
{
if (eErrorCode == CErrorCode::NoError)
{
sTemporaryValue.resize(nValueLength);
sValue = std::move(sTemporaryValue);
}
return eErrorCode;
}
}
while (true);
}

所以我做了初始 resize 因为我不能在第一次调用后这样做(因为那时它会删除内容,因为字符串最初是空的)。但是 resize 用零字符填充字符串,这让我很不高兴(我的意思是我知道无论如何我都会自己填充)。然后即使在成功运行后我也需要 resize 因为如果长度实际上更小我需要缩小。如果可以以更好的方式做到这一点,有什么建议吗?

最佳答案

由于您使用的是 DLL,我的理解是您使用的是 Windows,因此我将建议一个特定于 Windows 的解决方案。

嗯,安全地跨模块边界传递字符串的问题已经在 Windows 上通过 COM 内存分配器和 BSTR 解决了。

因此,与其传递一个字符串指针和一个大小指针,并检查调用者分配的缓冲区是否足够大,如果不够大,则返回所需的大小等。对我来说,只返回 BSTR 似乎更简单来自 DLL。

BSTR 是使用 COM 分配器分配的,因此您可以跨不同 模块边界分配和释放它们。

BSTR 也有很好的 C++ 包装器类,例如_bstr_t 或 ATL 的 CComBSTR。您可以在调用者的网站上使用它们。

一旦你有了一个 BSTR 实例,可能在调用者的网站上用一个方便的 RAII 包装器正确包装,你就可以轻松地将它转换为一个 std::wstring

或者,如果您想使用 Unicode UTF-8 编码和 std::string,您可以将 BSTR 的原生 UTF-16 编码转换为UTF-8,使用 WideCharToMultiByte()(this MSDN Magazine article 可以派上用场)。

额外阅读:Eric’s Complete Guide To BSTR Semantics

附言
如果您不想使用 BSTR 类型,您仍然可以使用 COM 提供的通用内存分配器:例如您可以在 DLL 中使用 CoTaskMemAlloc() 分配 (UTF-8) 字符串内存,并使用 CoTaskMemFree() 释放它 在调用者的站点。

关于c++ - 跨 DLL 边界的安全字符串复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39876327/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com