5

In an application of mine, I introduced a memory leak when I began to use std::async. After examining the problem with the tool Dr. memory, I found out that std::async leaks memory very often.

I made a quick test that reproduces the problem:

#include <Windows.h>
#include <algorithm>
#include <future>

using namespace std;

void testMethod()
{
    for (int i = 0; i < 4; i++)
        Sleep(10);
}

int main()
{
    for (int i = 0; i < 100; i++)
    {
        auto result = async(launch::async, testMethod);
        result.wait();
    }

    return 1;
}

How is it possible that the code above will leak memory on Windows? The problem does not occur on Linux. Dr. memory will produce the following log:

Error #1: REACHABLE LEAK 40 direct bytes 0x007badb8-0x007bade0 + 0 indirect bytes
# 0 replace_operator_new_nomatch                                   [d:\drmemory_package\common\alloc_replace.c:2732]
# 1 MSVCR120D.dll!Concurrency::details::SubAllocator::Alloc        [f:\dd\vctools\crt\crtw32\concrt\suballocator.cpp:201]
# 2 MSVCR120D.dll!Concurrency::details::ExternalContextBase::Alloc [f:\dd\vctools\crt\crtw32\concrt\externalcontextbase.cpp:238]
# 3 MSVCR120D.dll!Concurrency::Alloc                               [f:\dd\vctools\crt\crtw32\concrt\suballocator.cpp:34]
# 4 Concurrency::details::_AllocBase::operator new                 [c:\program files (x86)\microsoft visual studio 12.0\vc\include\concrt.h:298]
# 5 Concurrency::task<>::_TaskInitWithFunctor<>                    [c:\program files (x86)\microsoft visual studio 12.0\vc\include\ppltasks.h:3982]
# 6 Concurrency::task<>::_TaskInitMaybeFunctor<>                   [c:\program files (x86)\microsoft visual studio 12.0\vc\include\ppltasks.h:4551]
# 7 Concurrency::task<>::task<><>                                  [c:\program files (x86)\microsoft visual studio 12.0\vc\include\ppltasks.h:4198]
# 8 Concurrency::create_task<>                                     [c:\program files (x86)\microsoft visual studio 12.0\vc\include\ppltasks.h:4673]
# 9 std::_Task_async_state<>::_Task_async_state<><>                [c:\program files (x86)\microsoft visual studio 12.0\vc\include\future:906]
#10 std::_Get_associated_state<>                                   [c:\program files (x86)\microsoft visual studio 12.0\vc\include\future:1859]
#11 std::_Async<>      
lauw
  • 1,301
  • 2
  • 10
  • 10
  • 3
    Do you see just one leak, or 100 of them? My guess is, the first `async` call initializes a thread pool, which is then kept around until the program terminates. All other calls reuse the thread already running in the pool. This singleton is what triggers the false positive in the tool you use. – Igor Tandetnik Oct 09 '14 at 23:34
  • @IgorTandetnik There are multiple leaks in the test code. The last run there was a leak for every async call. In the test code I join every thread after calling it. Why would sync make so many threads while there are other threads available? – lauw Oct 10 '14 at 06:04
  • @IgorTandetnik My last comment was not correct, I did not run the correct code. There is indeed only one leak. Thanks for the help! – lauw Oct 10 '14 at 06:10

0 Answers0