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."
我同意。
我正在尝试使用 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."
我同意。