CppRest SDK(Casablanca) + static CRT link = caution! (might cause debug heap assert)

The C++ REST SDK(Casablanca) is currently only available to link dynamically(DLL) unless you build the library on your own. Here is the link describing the steps to link static to your application by downloading the source code and building it so.

If you’re using the cpprest sdk and unfortunately encountered the following debug heap assert, you probably made mismatch configuration for the Configuration Properties > C/C++ > Code Generation > Runtime Library for your main application against the cpprest DLL.

————————— Microsoft Visual C++ Runtime Library —————————

Debug Assertion Failed!

Program: C:\repo\test\cppresttest\Debug\cppresttest.exe File: f:\dd\vctools\crt\crtw32\misc\dbgheap.c Line: 1424

Expression: _pFirstBlock == pHead

For information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

debug heap assert
debug heap assert

The above link contains code snippet shows how simple cpprest is to read json value from STL fstream. However, if you run the code with Multi-threaded(/MT) enabled then it’ll end with a debug assert just right after the temporary std::wstring object as_string() returned is about to clean up itself.

In order to see what actually happened inside it, I enabled the gflag PeageHeap and captured a dump when the popup showed.

0:000> .frame 3
03 00ccf280 002b8cc3 cppresttest!std::allocator::deallocate+0x2c [c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 @ 573]
0:000> dv
this = 0x00ccf397
_Ptr = 0x05ab0fb8 “what do you think for this”
__formal = 0x20
0:000> !heap -p -a 0x05ab0fb8
address 05ab0fb8 found in
_DPH_HEAP_ROOT @ 5621000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize – VirtAddr VirtSize)
56247b8: 5ab0f98 64 – 5ab0000 2000
523b94ec verifier!AVrfDebugPageHeapAllocate+0x0000023c
77c557b7 ntdll!RtlDebugAllocateHeap+0x0000003c
77bf77ce ntdll!RtlpAllocateHeap+0x0004665a
77bb1134 ntdll!RtlAllocateHeap+0x0000014d
5151c6e1 MSVCR120D!_heap_alloc_base+0x00000051 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 58]
5152d72f MSVCR120D!_heap_alloc_dbg_impl+0x000001ff [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 431]
5152dbcd MSVCR120D!_nh_malloc_dbg_impl+0x0000001d [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 239]
5152db7a MSVCR120D!_nh_malloc_dbg+0x0000002a [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 302]
5152e5a9 MSVCR120D!malloc+0x00000019 [f:\dd\vctools\crt\crtw32\misc\dbgmalloc.c @ 56]
5151c26f MSVCR120D!operator new+0x0000000f [f:\dd\vctools\crt\crtw32\heap\new.cpp @ 59]
*** ERROR: Symbol file could not be found. Defaulted to export symbols for cpprest120d_2_5.dll –
10094601 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00017cc3
100a186e cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00024f30
100a16ef cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00024db1
1009eb54 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00022216
1009f8d6 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x00022f98
100a1da9 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x0002546b
10099e7f cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x0001d541
1022c95c cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001b001e
1022c9f4 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001b00b6
002bd377 cppresttest!wmain+0x00000237 [c:\repo\test\cppresttest\cppresttest\cppresttest.cpp @ 26]
0030c62a cppresttest!__tmainCRTStartup+0x0000011a [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 255]
0030c80d cppresttest!wmainCRTStartup+0x0000000d [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 165]
77897c04 kernel32!BaseThreadInitThunk+0x00000024
77bcad1f ntdll!__RtlUserThreadStart+0x0000002f
77bcacea ntdll!_RtlUserThreadStart+0x0000001b

_Ptr is the pHead and the call stack clearly shows it was allocated from the heap of MSVCR120D DLL. However, the another heap start address(_pFirstBlock) which failed to assert to be equal shows it’s allocated from different heap which was statically linked CRT more specifically.

00 00ccf128 00309bee cppresttest!_free_dbg_nolock+0x49d [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 1424]
0:000> !heap -p -a 0x092d6fd8
address 092d6fd8 found in
_DPH_HEAP_ROOT @ 5621000
in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize – VirtAddr VirtSize)
91e2680: 92d6fd8 1024 – 92d6000 3000
523b94ec verifier!AVrfDebugPageHeapAllocate+0x0000023c
77c557b7 ntdll!RtlDebugAllocateHeap+0x0000003c
77bf77ce ntdll!RtlpAllocateHeap+0x0004665a
77bb1134 ntdll!RtlAllocateHeap+0x0000014d
00325da1 cppresttest!_heap_alloc_base+0x00000051 [f:\dd\vctools\crt\crtw32\heap\malloc.c @ 58]
0030a52f cppresttest!_heap_alloc_dbg_impl+0x000001ff [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 431]
0030ab9d cppresttest!_nh_malloc_dbg_impl+0x0000001d [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 239]
0030ab3a cppresttest!_nh_malloc_dbg+0x0000002a [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 302]
0030a7ff cppresttest!_malloc_dbg+0x0000001f [f:\dd\vctools\crt\crtw32\misc\dbgheap.c @ 160]
0031d887 cppresttest!_getbuf+0x00000057 [f:\dd\vctools\crt\crtw32\stdio\_getbuf.c @ 58]
0031bd36 cppresttest!_filbuf+0x000000f6 [f:\dd\vctools\crt\crtw32\stdio\_filbuf.c @ 130]
00302643 cppresttest!fgetc+0x00000223 [f:\dd\vctools\crt\crtw32\stdio\fgetc.c @ 49]
002af947 cppresttest!std::_Fgetc+0x00000027 [c:\program files (x86)\microsoft visual studio 12.0\vc\include\fstream @ 39]
002bc2c7 cppresttest!std::basic_filebuf<char,std::char_traits >::uflow+0x000000b7 [c:\program files (x86)\microsoft visual studio 12.0\vc\include\fstream @ 478]
51fe7598 MSVCP120D!std::basic_streambuf<char,std::char_traits >::sbumpc+0x00000048 [f:\dd\vctools\crt\crtw32\stdhpp\streambuf @ 147]
10223aa1 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001a7163
102230a1 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001a6763
1022321b cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001a68dd
102281d1 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001ab893
10229b05 cpprest120d_2_5!web::http::experimental::listener::details::http_listener_impl::handle_request+0x001ad1c7
002bd238 cppresttest!wmain+0x000000f8 [c:\repo\test\cppresttest\cppresttest\cppresttest.cpp @ 22]
0030c62a cppresttest!__tmainCRTStartup+0x0000011a [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 255]
0030c80d cppresttest!wmainCRTStartup+0x0000000d [f:\dd\vctools\crt\crtw32\startup\crt0.c @ 165]
77897c04 kernel32!BaseThreadInitThunk+0x00000024
77bcad1f ntdll!__RtlUserThreadStart+0x0000002f
77bcacea ntdll!_RtlUserThreadStart+0x0000001b

Links

http://stackoverflow.com/questions/18882760/debug-assertion-failed-expression-pfirstblock-phead

http://stackoverflow.com/questions/21174593/downcasting-unique-ptrbase-to-unique-ptrderived

http://stackoverflow.com/questions/17885060/passing-reference-to-stl-vector-over-dll-boundary

https://casablanca.codeplex.com/discussions/442262

Advertisements

3 thoughts on “CppRest SDK(Casablanca) + static CRT link = caution! (might cause debug heap assert)

  1. Thanks. I meet the same problem today with cpprestsdk at version 2.8.0.
    And I found another problem that is i got lots of memory leaks when my program exit.
    Is there anyway to fix it?

    • If you’re developing it on the Windows, the latest service pack with Visual Studio 2015 supports new memory debug window which shows where the leaks are originated. For example, the VS 2015 provides the way making memory snapshot and comparing it between snapshots. Then it shows the location where the object allocated.Please refer to https://www.youtube.com/watch?v=HUZW8m_3XvE

      Or, there’s great too called ‘gflags’. You can also enable the Full PageHeap, and dump the memory allocation information with ‘heap -p command’ within WinDbg. (which illustrated in the above content)

      Thanks.

  2. Hi,
    Thanks for your reply.
    I don’t know how to use gflags to detect memory leaks.
    Here’s my environment:
    VS2013, win32 console application, MFC support, cpprestsdk 2.8.0 by nuget

    The code is :
    // Testtt.cpp : Defines the entry point for the console application.
    //

    #include “stdafx.h”
    #include “Testtt.h”

    #include
    #include
    #include
    #include

    using namespace web;
    using namespace http;
    using namespace utility;
    using namespace http::experimental::listener;
    using namespace concurrency::streams;

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif

    class CommandHandler
    {
    public:
    CommandHandler(){}
    CommandHandler(utility::string_t url);
    pplx::task open() { return m_listener.open(); }
    pplx::task close() { return m_listener.close(); }
    private:
    void handle_get(http_request message);

    http_listener m_listener;
    };

    CommandHandler::CommandHandler(utility::string_t url) : m_listener(url)
    {
    m_listener.support(methods::GET, std::bind(&CommandHandler::handle_get, this, std::placeholders::_1));

    }

    void CommandHandler::handle_get(http_request message)
    {
    ucout << "Method: " << message.method() << std::endl;
    ucout << "URI: " << http::uri::decode(message.relative_uri().path()) << std::endl;
    ucout << "Query: " << http::uri::decode(message.relative_uri().query()) << std::endl << std::endl;

    message.reply(status_codes::OK, "ACCEPTED");
    }

    // The one and only application object

    CWinApp theApp;

    using namespace std;

    int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
    {
    int nRetCode = 0;

    HMODULE hModule = ::GetModuleHandle(NULL);

    if (hModule != NULL)
    {
    // initialize MFC and print and error on failure
    if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
    {
    // TODO: change error code to suit your needs
    _tprintf(_T("Fatal Error: MFC initialization failed\n"));
    nRetCode = 1;
    }
    else
    {
    try
    {
    ucout.imbue(std::locale("chs"));

    string_t address = U("http://*:8090&quot;);
    uri_builder uri(address);
    auto addr = uri.to_uri().to_string();
    CommandHandler handler(addr);
    handler.open().wait();
    ucout << U("Listening for request at: ") << addr << std::endl;
    ucout << U("Press key to quit…") << std::endl;

    std::string line;
    std::getline(std::cin, line);
    handler.close().wait();
    }
    catch (std::exception ex)
    {
    ucout << U("Exception: ") << ex.what() << std::endl;
    ucout << U("Press EnterKey to quit….") << std::endl;
    std::string line;
    std::getline(std::cin, line);
    }
    }
    }
    else
    {
    // TODO: change error code to suit your needs
    _tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
    nRetCode = 1;
    }

    return nRetCode;
    }

    Then i start debugging, It looks run well.
    But after executing, I've been report lots of memory leaks. Is this my fault or a bug in cpprestsdk2.8.0?

    By the way. Are u chinese? I am chinese. 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s