2013-03-04 20 views
10

Clang ++ 3.2 trên ArchLinux (i686) được sử dụng để xây dựng C++ 11 mã sauClang ++ tạo ra thực thi mà rò rỉ bộ nhớ, khoảng std :: chức năng và lambda

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

Với clang++ test.cpp -std=c++0x && valgrind --leak-check=full --log-file=tmp.log.memcheck ./a.out sau đó tôi nhận được

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

Tôi không chắc liệu có bất kỳ vấn đề nào với mã đó (và chỉ gây ra rò rỉ ONE byte), nhưng sẽ không có rò rỉ bộ nhớ nếu sử dụng g ++ 4.7 để biên dịch. Bất kỳ đề nghị về điều đó?

+1

FWIW nó báo cáo với '-v --leakcheck = full' chỉ trên Debian tôi. Có nghĩa là nó có thể là một loại trừ đã – sehe

+1

Tôi muốn cược rằng nếu bạn đã thoát khỏi 'tĩnh' thì" rò rỉ "sẽ biến mất. – ildjarn

+0

@ildjarn Trong trường hợp này không quan trọng nếu 'gen' là' tĩnh' nhưng trong chương trình của tôi, nhiều đối tượng chia sẻ hàm này. Nhưng tôi đã nhận thấy rằng sự rò rỉ cũng sẽ biến mất nếu một đối tượng hàm mới được xây dựng mỗi lần, khác với một đối tượng tĩnh. Cảm ơn lời khuyên của bạn. – neuront

Trả lời

0

Biến tĩnh nổi tiếng 'gây ra' những rò rỉ bộ nhớ trong valgrind cho các đối tượng phức tạp mà ngoài việc phân bổ một cái gì đó trên heap (ví dụ như container STL vv).

Trong thực tế không có gì phải lo lắng, nhưng tất nhiên nó phá hủy chương trình 'của tôi không bị rò rỉ' -fact và làm cho rò rỉ thực sự khó phát hiện hơn.

Tôi giả sử g ++ chỉ quản lý để giữ cho trình tạo hoàn toàn trong khu vực BSS trong khi clang thấy cần phải phân bổ một byte trên heap.

+0

Đừng quên rằng bạn có thể tạo ra một sự đàn áp cho rò rỉ bộ nhớ cụ thể bằng cách sử dụng tùy chọn dòng lệnh '--gen-suppressions = yes' cho valgrind. –

1

Việc phân bổ đang xảy ra ở đây :

return [=]() 

nào nói "Chụp tất cả mọi thứ đó không phải là một tham số theo giá trị", bao gồm "std :: cout" vv, có nghĩa là làm cho bản sao của chúng.

Mã sau vượt qua cùng một biên dịch & kiểm tra valgrind mà không có lỗi, nhưng với báo trước rằng lập trình viên chịu trách nhiệm đảm bảo tuổi thọ của tham số "gen" của hành động dài hơn tuổi thọ của 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; 
} 

cũng Xem http://en.cppreference.com/w/cpp/language/lambda