11

ArchLinux (i686) 上的 Clang++ 3.2 用于构建以下 C++11 代码

#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;
}

clang++ test.cpp -std=c++0x && valgrind --leak-check=full --log-file=tmp.log.memcheck ./a.out然后我得到

==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)

我不确定该代码是否有任何问题(并且只导致一个字节泄漏),但如果使用 g++ 4.7 编译,则不会有内存泄漏。对此有何建议?

4

2 回答 2

1

分配发生在这里

    return [=]()

上面写着“按值捕获不是参数的所有内容”,包括“std::cout”等,这意味着复制它们。

以下代码通过了相同的编译和 valgrind 检查而没有错误,但需要注意的是程序员负责确保 act 的“gen”参数的生命周期长于 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;
}

另请参阅http://en.cppreference.com/w/cpp/language/lambda

于 2013-05-28T01:26:26.880 回答
0

众所周知,静态变量会在 valgrind 中为复杂对象“导致”这些内存泄漏,这些对象还会在堆上分配一些东西(例如 STL 容器等)。

实际上,没有什么可担心的,但它当然会破坏“我的程序没有泄漏”的事实,并使真正的泄漏更难被发现。

我假设 g++ 只是设法将生成器完全保留在 BSS 区域中,而 clang 认为需要在堆上分配一个字节。

于 2013-03-25T23:37:46.663 回答