2013-03-04 7 views
10

Clang ++ 3,2 su ArchLinux (i686) viene utilizzato per costruire i seguenti C++ 11 codiciClang ++ genera eseguibile che perde la memoria, circa std :: funzione e 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; 
} 

Con clang++ test.cpp -std=c++0x && valgrind --leak-check=full --log-file=tmp.log.memcheck ./a.out allora ottengo

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

Non sono sicuro se c'è qualche problema con quel codice (e causa solo UNA perdita di byte), ma non ci saranno perdite di memoria se si utilizza g ++ 4.7 per compilare. Qualche suggerimento a riguardo?

+1

FWIW E 'riportato con '-v --leakcheck = full' solo sulla mia Debian. Il che significa che probabilmente è già un'esclusione – sehe

+1

Scommetto che se ti liberassi di 'static', allora la" perdita "scomparirebbe. – ildjarn

+0

@ildjarn In questo caso non importa se 'gen' è' static' ma nel mio programma molti oggetti condividono questo functor. Ma ho notato che la perdita sparirà anche se un nuovo oggetto funzione viene costruito ogni volta, diverso da uno statico. Grazie per il tuo consiglio. – neuront

risposta

0

Le variabili statiche notoriamente causano queste perdite di memoria in valgrind per oggetti complessi che in più allocano qualcosa sullo heap (come ad esempio contenitori STL, ecc.).

In pratica non c'è nulla di cui preoccuparsi, ma ovviamente distrugge il 'il mio programma è privo di perdite' e rende difficile individuare le perdite reali.

Suppongo che g ++ riesca a mantenere il generatore interamente nell'area BSS mentre clang vede la necessità di allocare un byte sull'heap.

+0

Non dimenticare che è possibile generare una soppressione per perdite di memoria specifiche usando l'opzione della riga di comando '--gen-suppressions = yes' per valgrind. –

1

L'assegnazione avviene qui:

return [=]() 

che dice "catturare tutto ciò che non è un parametro per valore", tra cui "std :: cout", ecc, che significa fare copie di loro.

Il seguente codice passa lo stesso compile & check valgrind senza errori, ma con l'avvertenza che il programmatore è responsabile di garantire la durata del parametro "gen" di act è più lungo della durata del 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; 
} 

Vedi anche http://en.cppreference.com/w/cpp/language/lambda

Problemi correlati