I've added Casablanca to an application I'm building that works on Windows and Linux. When I have Casablanca send REST requests to our server on Windows, everything works fine and I don't get any crash. However, on Linux the application runs but crashes anytime I try to send a request with Casablanca and I'm not sure why. It appears to be some kind of memory corruption due to bad strings, but I'm having difficulty figuring out what's going wrong. Note that the exact same code works fine on Windows - the only difference is that Windows uses wide strings and Linux doesn't (due to Casablanca's restriction here).
Here's the code I'm using (all are my files):
RestClient.h
```
private:
/// <summary>
/// The internal client used to send REST requests (Casablanca).
/// </summary>
web::http::client::http_client m_client;
```
RestClient.cpp
```
// Server root URL is a std::string that points to my server.
RestClient::RestClient(const LamaString& serverRootUri)
: m_client(serverRootUri)
{
}
HttpResponse RestClient::Get(const LamaString& url)
{
http_request request = BuildStandardHttpRequest(url, methods::GET);
return Send(request);
}
http_request RestClient::BuildStandardHttpRequest(
const LamaString& url,
const LamaString& method)
{
http_request request(method);
uri_builder builder(url);
request.set_request_uri(builder.to_uri());
request.headers().add(header_names::accept, U("application/json"));
request.headers().add(U(APPLICATION_ID_HTTP_HEADER), U(APPLICATION_ID));
request.headers().add(U(MACHINE_ID_HTTP_HEADER), U(MACHINE_ID));
return request;
}
HttpResponse RestClient::Send(http_request request)
{
// This call is where the memory corruption occurs, it stops program execution here on Linux.
task<http_response> task = m_client.request(request);
return HttpResponse();
}
```
Here's the error I'm getting in Eclipse:
malloc(): memory corruption: 0x0000000001b17c10 ***
Here's the call stack I'm seeing:
```
__GI_raise() at raise.c:56 0x7ffff2b99cc9
__GI_abort() at abort.c:89 0x7ffff2b9d0d8
__libc_message() at libc_fatal.c:175 0x7ffff2bd6394
malloc_printerr() at malloc.c:4,996 0x7ffff2be3f36
_int_malloc() at malloc.c:3,447 0x7ffff2be3f36
__GI___libc_malloc() at malloc.c:2,891 0x7ffff2be57b0
operator new() at 0x7ffff34a2dad
__gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<web::http::details::_http_response, std::allocator<web::http::details::_http_response>, (__gnu_cxx::_Lock_policy)2> >::allocate at new_allocator.h:104 0x7ffff4dff162
std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<web::http::details::_http_response, std::allocator<web::http::details::_http_response>, (__gnu_cxx::_Lock_policy)2> > >::allocate at alloc_traits.h:351 0x7ffff4dfe518
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<web::http::details::_http_response, std::allocator<web::http::details::_http_response>> at shared_ptr_base.h:499 0x7ffff4dfd5f6
std::__shared_ptr<web::http::details::_http_response, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<web::http::details::_http_response>> at shared_ptr_base.h:957 0x7ffff4dfc4b0
std::shared_ptr<web::http::details::_http_response>::shared_ptr<std::allocator<web::http::details::_http_response>>() at shared_ptr.h:316 0x7ffff4df9a50
std::allocate_shared<web::http::details::_http_response, std::allocator<web::http::details::_http_response>>() at shared_ptr.h:598 0x7ffff4df66f0
std::make_shared<web::http::details::_http_response>() at shared_ptr.h:614 0x7ffff4df2fb1
web::http::http_response::http_response() at http_msg.h:391 0x7ffff4df0da0
pplx::details::_ResultHolder<web::http::http_response>::_ResultHolder() at pplxtasks.h:832 0x7ffff4e03dde
pplx::details::_Task_impl<web::http::http_response>::_Task_impl() at pplxtasks.h:2,412 0x7ffff4fab291
__gnu_cxx::new_allocator<pplx::details::_Task_impl<web::http::http_response> >::construct<pplx::details::_Task_impl<web::http::http_response><pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> >() at new_allocator.h:120 0x7ffff4faac21
std::allocator_traits<std::allocator<pplx::details::_Task_impl<web::http::http_response> > >::_S_construct<pplx::details::_Task_impl<web::http::http_response><pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> >() at alloc_traits.h:254 0x7ffff4fa9db9
std::allocator_traits<std::allocator<pplx::details::_Task_impl<web::http::http_response> > >::construct<pplx::details::_Task_impl<web::http::http_response><pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> >() at alloc_traits.h:393 0x7ffff4fa8d72
std::_Sp_counted_ptr_inplace<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, (__gnu_cxx::_Lock_policy)2>::_Sp_counted_ptr_inplace<pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> at shared_ptr_base.h:399 0x7ffff4fa6916
__gnu_cxx::new_allocator<std::_Sp_counted_ptr_inplace<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, (__gnu_cxx::_Lock_policy)2> >::construct<std::_Sp_counted_ptr_inplace<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, (__gnu_cxx::_Lock_policy)2><std::allocator<pplx::details::_Task_impl<web::http::http_response> > const, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> > at new_allocator.h:120 0x7ffff4fa4d65
std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, (__gnu_cxx::_Lock_policy)2> > >::_S_construct<std::_Sp_counted_ptr_inplace<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, (__gnu_cxx::_Lock_policy)2><std::allocator<pplx::details::_Task_impl<web::http::http_response> > const, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> > at alloc_traits.h:254 0x7ffff4fa2f45
std::allocator_traits<std::allocator<std::_Sp_counted_ptr_inplace<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, (__gnu_cxx::_Lock_policy)2> > >::construct<std::_Sp_counted_ptr_inplace<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, (__gnu_cxx::_Lock_policy)2><std::allocator<pplx::details::_Task_impl<web::http::http_response> > const, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> > at alloc_traits.h:393 0x7ffff4fa0286
std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> at shared_ptr_base.h:502 0x7ffff4f9e335
std::__shared_ptr<pplx::details::_Task_impl<web::http::http_response>, (__gnu_cxx::_Lock_policy)2>::__shared_ptr<std::allocator<pplx::details::_Task_impl<web::http::http_response> >, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&> at shared_ptr_base.h:957 0x7ffff4f9b1db
std::shared_ptr<pplx::details::_Task_impl<web::http::http_response> >::shared_ptr<std::allocator<pplx::details::_Task_impl<web::http::http_response> >, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&>() at shared_ptr.h:316 0x7ffff4f9827e
std::allocate_shared<pplx::details::_Task_impl<web::http::http_response>, std::allocator<pplx::details::_Task_impl<web::http::http_response> >, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&>() at shared_ptr.h:598 0x7ffff4f95972
std::make_shared<pplx::details::_Task_impl<web::http::http_response>, pplx::details::_CancellationTokenState*&, pplx::scheduler_ptr&>() at shared_ptr.h:614 0x7ffff4f9252d
pplx::details::_Task_ptr<web::http::http_response>::_Make() at pplxtasks.h:1,429 0x7ffff4f8e519
pplx::task<web::http::http_response>::_CreateImpl() at pplxtasks.h:3,630 0x7ffff4f89d3f
pplx::task<web::http::http_response>::task<pplx::task_completion_event<web::http::http_response> >() at pplxtasks.h:3,304 0x7ffff4f8e325
pplx::create_task<pplx::task_completion_event<web::http::http_response> >() at pplxtasks.h:4,726 0x7ffff4f89ba0
0x0
```
I also tried to reproduce the error directly by removing all Casablanca code except calling some of the task creation code directly like the library does internally. When I do this, I get another exception when attempting to destroy the _http_response internal structure. Note this snippet of code also works fine on Windows and doesn't crash. In this case I'm not passing strings of any kind to Casablanca and it's still crashing, so I'm not sure why this is.
Here's the small snippet I tried:
```
task_completion_event<http_response> e;
create_task(e);
```
Here's the callstack I get after the task goes out of scope (truncated due to character limit when posting):
Thread #1 [app] 20995 [core: 0] (Suspended : Signal : SIGSEGV:Segmentation fault)
__gnu_cxx::__exchange_and_add() at atomicity.h:49 0xba9942
__gnu_cxx::__exchange_and_add_dispatch() at atomicity.h:82 0xba99d7
std::string::_Rep::_M_dispose() at basic_string.h:246 0xbb21e0
std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string() at
...
Here's what the locals window shows on the string:
_M_p char * 0x1 <error: Cannot access memory at address 0x1>
Any help is appreciated!
Comments: Been digging into this for about 2 weeks now, so I may have to move on and use some other approach if I can't get this working. I'm getting all kinds of memory corruption problems anytime I use the http_request structure on Linux (or if the Casablanca library uses it at all). If I don't use that structure, there are no memory errors reported with Valgrind. I've tried creating a sample application that repros all the libraries includes, compiler flags, etc. that I use in my larger application but I've been unable to reproduce the problems in a sample app.
Here's the larger application code (I trimmed usage of the Casablanca http_request object as much as I could).
```
int main(int argc, char* argv[])
{
{
// Comment out this line and no corruption will occur or be reported.
http_request request = http_request();
}
return 0;
}
```
As you can see, I'm not even making a request. Simply creating this object with the default constructor and allowing it to go out of scope causes corruption problems. If I don't use Casablanca, no memory issues are reported and the application runs ok from what I can tell. From the Valgrind errors, the best guess I have is that some memory inside the http_request object is being freed more than once during destruction, but I'm not sure.
Here's the Valgrind error:
==27256== Memcheck, a memory error detector
==27256== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==27256== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==27256== Command: ./src/application
==27256== Parent PID: 10633
==27256==
==27256== Invalid write of size 8
==27256== at 0x7FBFA99: std::unique_ptr<web::http::details::_http_server_context, std::default_delete<web::http::details::_http_server_context> >::~unique_ptr() (unique_ptr.h:185)
==27256== by 0x7FBEAF9: web::http::details::_http_request::~_http_request() (in /usr/lib/x86_64-linux-gnu/libcpprest.so.2.6)
==27256== by 0xD5ABAE: void __gnu_cxx::new_allocator<web::http::details::_http_request>::destroy<web::http::details::_http_request>(web::http::details::_http_request*) (new_allocator.h:124)
==27256== by 0xD5AB64: std::enable_if<std::allocator_traits<std::allocator<web::http::details::_http_request> >::__destroy_helper<web::http::details::_http_request>::value, void>::type std::allocator_traits<std::allocator<web::http::details::_http_request> >::_S_destroy<web::http::details::_http_request>(std::allocator<web::http::details::_http_request>&, web::http::details::_http_request*) (alloc_traits.h:281)
==27256== by 0xD5AB1A: void std::allocator_traits<std::allocator<web::http::details::_http_request> >::destroy<web::http::details::_http_request>(std::allocator<web::http::details::_http_request>&, web::http::details::_http_request*) (alloc_traits.h:405)
==27256== by 0xD5AA62: std::_Sp_counted_ptr_inplace<web::http::details::_http_request, std::allocator<web::http::details::_http_request>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==27256== by 0xC075CF: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:144)
==27256== by 0xC0670A: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:546)
==27256== by 0xD58B11: std::__shared_ptr<web::http::details::_http_request, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:781)
==27256== by 0xD58B2B: std::shared_ptr<web::http::details::_http_request>::~shared_ptr() (shared_ptr.h:93)
==27256== by 0xD58B75: web::http::http_request::~http_request() (http_msg.h:790)
==27256== by 0xD5582E: main (application.cpp:706)
==27256== Address 0xf145888 is 168 bytes inside a block of size 392 free'd
==27256== at 0x4C2C171: operator delete(void*) (vg_replace_malloc.c:575)
==27256== by 0xD5AA39: std::_Sp_counted_ptr_inplace<web::http::details::_http_request, std::allocator<web::http::details::_http_request>, (__gnu_cxx::_Lock_policy)2>::~_Sp_counted_ptr_inplace() (shared_ptr_base.h:403)
==27256== by 0x7FC03E9: std::default_delete<web::http::details::_http_server_context>::operator()(web::http::details::_http_server_context*) const (unique_ptr.h:67)
==27256== by 0x7FBFA94: std::unique_ptr<web::http::details::_http_server_context, std::default_delete<web::http::details::_http_server_context> >::~unique_ptr() (unique_ptr.h:184)
==27256== by 0x7FBEAF9: web::http::details::_http_request::~_http_request() (in /usr/lib/x86_64-linux-gnu/libcpprest.so.2.6)
==27256== by 0xD5ABAE: void __gnu_cxx::new_allocator<web::http::details::_http_request>::destroy<web::http::details::_http_request>(web::http::details::_http_request*) (new_allocator.h:124)
==27256== by 0xD5AB64: std::enable_if<std::allocator_traits<std::allocator<web::http::details::_http_request> >::__destroy_helper<web::http::details::_http_request>::value, void>::type std::allocator_traits<std::allocator<web::http::details::_http_request> >::_S_destroy<web::http::details::_http_request>(std::allocator<web::http::details::_http_request>&, web::http::details::_http_request*) (alloc_traits.h:281)
==27256== by 0xD5AB1A: void std::allocator_traits<std::allocator<web::http::details::_http_request> >::destroy<web::http::details::_http_request>(std::allocator<web::http::details::_http_request>&, web::http::details::_http_request*) (alloc_traits.h:405)
==27256== by 0xD5AA62: std::_Sp_counted_ptr_inplace<web::http::details::_http_request, std::allocator<web::http::details::_http_request>, (__gnu_cxx::_Lock_policy)2>::_M_dispose() (shared_ptr_base.h:407)
==27256== by 0xC075CF: std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release() (shared_ptr_base.h:144)
==27256== by 0xC0670A: std::__shared_count<(__gnu_cxx::_Lock_policy)2>::~__shared_count() (shared_ptr_base.h:546)
==27256== by 0xD58B11: std::__shared_ptr<web::http::details::_http_request, (__gnu_cxx::_Lock_policy)2>::~__shared_ptr() (shared_ptr_base.h:781)
Any thoughts on how I can debug this further or things I can try are appreciated - thanks!