http_client 构造函数内部崩溃(Casablanca SDK)

Crash inside http_client constructor (Casablanca SDK)

我正在尝试使用 Casablanca 来使用 REST api。 我一直在关注微软教程,但我怎么会崩溃,我无法弄清楚。

我正在使用 visual studio 2017 和 C++11

我编写了一个 GetRequest() 函数,它在一个新的空项目中使用时有效,但当我尝试在我的项目(具有数百万代码行的非常大的项目)中使用它时。 我在文件 xmemory0 第 118 行 http_client 的构造函数中崩溃。

const uintptr_t _Ptr_container = _Ptr_user[-1];

这是一个 link 调用堆栈:https://i.imgur.com/lBm0Hv7.png

void RestManager::GetRequest()
{
    auto fileStream = std::make_shared<ostream>();

    // Open stream to output file.
    pplx::task<void> requestTask = fstream::open_ostream(U("results.html")).then([=](ostream outFile)
    {
        *fileStream = outFile;

        // Create http_client to send the request.
        http_client client(U("XXX/XXX.svc/"));

        // Build request URI and start the request.
        uri_builder builder(U("/IsLive"));
        builder.append_query(U("q"), U("cpprestsdk github"));
        return client.request(methods::GET, builder.to_string());
    })

        // Handle response headers arriving.
        .then([=](http_response response)
    {
        printf("Received response status code:%u\n", response.status_code());

        // Write response body into the file.
    return response.body().read_to_end(fileStream->streambuf());
    })    

        // Close the file stream.
        .then([=](size_t)
    {
        return fileStream->close();
    });

    // Wait for all the outstanding I/O to complete and handle any exceptions
    try
    {
        requestTask.wait();
    }
    catch (const std::exception &e)
    {
        printf("Error exception:%s\n", e.what());
    }

}

编辑:我只想补充一点,http_client 构造函数是问题所在。无论我作为参数发送什么,它总是在其中崩溃。

奇怪的是,当我只创建一个调用此函数的 main() 时它并没有崩溃。 我想这一定是由于一些内存问题,但我不知道我该如何调试它。 有人对此有想法吗?

谢谢,祝你有美好的一天!

我想这个问题非常具体,可能永远不会有人关心,但我仍然会更新我发现的所有相关信息。

在这个项目中,我们使用的是自定义分配器,如果我没记错的话,不可能将我们的自定义分配器提供给这个库,这会导致许多随机崩溃。

修复它的一个很好的选择是对该库使用静态版本,但是,由于我们使用了很多动态库,所以这个选项对我们来说是不可能的。

如果你是我的情况,我建议使用libcurl和rapidjson,它使用起来有点困难,但你可以达到同样的目的。

我在 ubuntu 上遇到过类似的问题。它在空项目中工作,但在放入现有大型项目时随机崩溃,抱怨内存损坏。

事实证明,现有项目加载了一个内部使用 cpprestsdk (casablanca) 的专有库。即使 cpprestsdk 是静态链接的,它的符号仍然作为弱符号导出。所以要么我的代码崩溃,要么专有库崩溃。

理想情况下,我的项目可以分成几个库,并用RTLD_LOCAL加载它们以避免符号冲突。但是我项目中的专有库只接受RTLD_GLOBAL,否则会崩溃...所以导入顺序和标志变得很重要:

dlopen("my-lib-uses-cpprest", RTLD_LOCAL); //To avoid polluting the global
dlopen("proprietary-lib-with-built-in-cpprest", RTLD_GLOBAL); //In my case, this lib must be global
dlopen("another-lib-uses-cpprest", RTLD_DEEPBIND); //To avoid being affected by global

"it will probably never concern anyone."

我同意。