Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clang++ generates executable that leaks memory, about std::function and lambda

Clang++ 3.2 on ArchLinux (i686) is used to build the following C++11 codes

#include <iostream>
#include <functional>

typedef std::function<void ()> Action;
typedef std::function<int ()> Generator;

Action act(Generator const& gen)
{
    return [=]()
    {
        std::cout << gen() << std::endl;
    };
}

int main()
{
    static Generator const gen([]() { return 0; });
    act(gen);
    return 0;
}

With clang++ test.cpp -std=c++0x && valgrind --leak-check=full --log-file=tmp.log.memcheck ./a.out then I get

==600== HEAP SUMMARY:
==600==     in use at exit: 1 bytes in 1 blocks
==600==   total heap usage: 3 allocs, 2 frees, 18 bytes allocated
==600== 
==600== 1 bytes in 1 blocks are definitely lost in loss record 1 of 1
==600==    at 0x402B124: operator new(unsigned int) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==600==    by 0x8048D4F: std::_Function_base::_Base_manager<main::$_1>::_M_clone(std::_Any_data&, std::_Any_data const&, std::integral_constant<bool, false>) (in /home/neuront/a.out)
==600==    by 0x8048C21: std::_Function_base::_Base_manager<main::$_1>::_M_manager(std::_Any_data&, std::_Any_data const&, std::_Manager_operation) (in /home/neuront/a.out)
==600==    by 0x8049455: std::function<int ()>::function(std::function<int ()> const&) (in /home/neuront/a.out)
==600==    by 0x8049283: std::function<int ()>::function(std::function<int ()> const&) (in /home/neuront/a.out)
==600==    by 0x80489B1: act(std::function<int ()> const&) (in /home/neuront/a.out)
==600==    by 0x8048A6C: main (in /home/neuront/a.out)
==600== 
==600== LEAK SUMMARY:
==600==    definitely lost: 1 bytes in 1 blocks
==600==    indirectly lost: 0 bytes in 0 blocks
==600==      possibly lost: 0 bytes in 0 blocks
==600==    still reachable: 0 bytes in 0 blocks
==600==         suppressed: 0 bytes in 0 blocks
==600== 
==600== For counts of detected and suppressed errors, rerun with: -v
==600== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

I'm not sure whether there's any problem with that code (and causes just ONE byte leak), but there will be no memory leak if using g++ 4.7 to compile. Any suggestion about that?

like image 370
neuront Avatar asked Mar 04 '13 08:03

neuront


People also ask

What is memory leakage how it is created?

The memory leak occurs, when a piece of memory which was previously allocated by the programmer. Then it is not deallocated properly by programmer. That memory is no longer in use by the program. So that place is reserved for no reason. That's why this is called the memory leak.

How do you tell if C++ program has a memory leak?

In visual studio, there is a built in detector for memory leak called C Runtime Library. When your program exits after the main function returns, CRT will check the debug heap of your application. if you have any blocks still allocated on the debug heap, then you have memory leak..

What is memory leak in stack?

A memory leak is typically associated with dynamic memory allocation(s) and then losing the ability to deallocate it. For example: // Memory leak int x; int *q = new int; q = &x; // memory leak because the "allocated" q is lost. With RAII and not using new + delete for memory management, it's easily avoidable in C++.

What is memory leak in dynamic memory allocation?

Memory leaks occur when new memory is allocated dynamically and never deallocated. In C programs, new memory is allocated by the malloc or calloc functions, and deallocated by the free function.


1 Answers

The allocation is happening here:

    return [=]()

Which says "Capture everything that's not a parameter by value", including "std::cout" etc, which means making copies of them.

The following code passes the same compile & valgrind check without the errors, but with the caveat that the programmer is responsible for ensuring the lifetime of act's "gen" parameter is longer than the lifetime of the lambda.

#include <iostream>
#include <functional>

typedef std::function<void ()> Action;
typedef std::function<int ()> Generator;

Action act(Generator const& gen)
{
    return [&gen]()
    {
        std::cout << gen() << std::endl;
    };
}

int main()
{
    static Generator const gen([]() { return 0; });
    act(gen);
    return 0;
}

See also http://en.cppreference.com/w/cpp/language/lambda

like image 96
kfsone Avatar answered Oct 11 '22 08:10

kfsone