替换 to_utf8string 以确保在 C++ DLL 中对 Windows 7 进行正确的字符串编码

Replace to_utf8string to ensure proper string encoding on Windows 7 in a C++ DLL

我有一个遗留的 C++ 代码,它被写成一个 dll,可以在 Windows10 上调用。一个新的要求是允许这个 dll 在早期的 Windows(7 嵌入式,也可选择 XP)。简而言之,代码应该显示 REST 响应的 body

问题是,当调用 Windows 7 而不进行任何修改时,会出现额外的(有时是不可见的)字符,尤其是在显示输出的开头。

下面的代码是一个简化版本,我相信 to_utf8string 是问题的根源。为了让这个 dll 在 Windows 7 上正常工作,我应该使用什么其他功能?

const char* foo(const char* param)
{
    web::http::http_response resp = other_foo(param).get();
    std::string utf8Response;

    web::json::value json = resp.extract_json().get();
    utf8Response = utility::conversions::to_utf8string(json.serialize());

    return utf8Response.c_str();
}

Windows7 上的两个示例输出:

  1. 应该是:{"statusCode": 400,

  2. 应该是:{"status":

问题与字符编码无关,也与使用的OS无关。该函数是 returning 一个指向无效内存的 悬空指针 !

函数正在声明一个局部 std::string 变量,该变量在函数退出时超出范围。它是 return 指向 std::string 的内部字符数据的指针,当 std::string 被销毁时,它会被释放。

为了解决这个问题,该函数必须 return 指向 动态分配内存的指针 调用者随后可以释放(或传回 DLL 以释放) 在稍后使用数据完成时。例如:

const char* foo(const char* param)
{
    web::http::http_response resp = other_foo(param).get();
    web::json::value json = resp.extract_json().get();
    std::string utf8Response = utility::conversions::to_utf8string(json.serialize());

    // the caller can use CoTaskMemFree() to free this returned memory...
    size_t size = utf8Response.size() + 1; // +1 for null terminator
    char *ptr = static_cast<char*>(CoTaskMemAlloc(size));
    if (ptr)
        std::memcpy(ptr, utf8Response.c_str(), size);
    return ptr;
}
const char* response = foo(param);
if (response) {
    ...
    CoTaskMemFree(response);
}

或:

const char* foo(const char* param)
{
    web::http::http_response resp = other_foo(param).get();
    web::json::value json = resp.extract_json().get();
    std::string utf8Response = utility::conversions::to_utf8string(json.serialize());

    // the caller must call free_foo_result() to free this memory...
    size_t size = utf8Response.size() + 1; // +1 for null terminator
    char *ptr = new(std::nothrow) char[size];
    if (ptr)
        std::memcpy(ptr, utf8Response.c_str(), size);
    return ptr;
}

void free_foo_result(const char *data)
{
    delete[] data;
}
const char* response = foo(param);
if (response) {
    ...
    free_foo_result(response);
}

如果 re-writing 执行这些额外函数调用的 EXE 不是一个选项,那么 DLL 将不得不缓存 JSON 数据,以便它可以在 return 之后继续存在,例如:

const char* foo(const char* param)
{
    static thread_local std::string utf8Response;

    web::http::http_response resp = other_foo(param).get();
    web::json::value json = resp.extract_json().get();
    utf8Response = utility::conversions::to_utf8string(json.serialize());

    return utf8Response.c_str();
}