2012-05-25 12 views
14

Ho un metodo dichiarato in questo modo:Se si specifica un valore predefinito per un argomento di tipo "std :: string &" in C++, ciò potrebbe causare una perdita di memoria?

/*! 
\brief Removes the leading and trailing white space from a string. 
\param s The string to remove the white space from. 
\param white_chars Characters to be considered as whitespace. 
*/ 
std::string Trim(const std::string &s, const std::string &white_chars = " \t\n\r"); 

La definizione del metodo è poco interessante, ma qui è in ogni caso:

std::string Trim(const std::string &s, const std::string &white_chars) 
{ 
    size_t startidx = s.find_first_not_of(white_chars); 
    if (startidx == std::string::npos) return ""; 
    size_t endidx = s.find_last_not_of(white_chars); 
    return s.substr(startidx, endidx - startidx + 1); 
} 

Ora nella maggior parte dei usi di questo metodo, mi forniscono solo il primo argomento. Valgrind mi dà il seguente avviso

==3338== 68 bytes in 2 blocks are possibly lost in loss record 4,639 of 7,212 
==3338== at 0x4C2B1C7: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3338== by 0x728CA88: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16) 
==3338== by 0x728E2B4: char* std::string::_S_construct<char*>(char*, char*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16) 
==3338== by 0x728E414: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&, unsigned long, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16) 
==3338== by 0x728E441: std::string::substr(unsigned long, unsigned long) const (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.16) 
==3338== by 0x6965F0A: str::Trim(std::string const&, std::string const&) (appbase.cpp:90) 
==3338== by 0x5F481D7: netopt::Element::set_ID(std::string const&) (netopt_elem.cpp:85) 

Nota "i blocchi possono essere persi"? Ho visto perdite di memoria dove Valgrind mi dice "i blocchi sono definitivamente persi", ma questo è un messaggio meno sicuro.

Quindi la domanda diventa, sto causando una perdita di memoria assegnando un valore predefinito a un std::string &? In tal caso, cosa sto sbagliando?

risposta

13

Non c'è alcun problema tecnico, ma la creazione filosofica di uno std::string temporaneo ad ogni chiamata non è così piacevole. Soprattutto con libstdC++ (che sembra utilizzare) poiché causa ogni volta un'allocazione di memoria (mancanza di Short String Optimization).

Dal find_first_not_of ha un sovraccarico di prendere un char const*, sarebbe meglio per fornire due overload invece:

// First, the one with the default argument, but without a temporary 
std::string Trim(std::string const& s, char const* white_chars = " \t\n\r"); 

// Second, for convenience, one with a `std::string` 
std::string Trim(std::string const& s, std::string const& white_chars); 

Questo significa anche che quando si chiama Trim(xx, "abc") eviterete la temporanea std::string viene generata :)

Ovviamente, la soluzione di overkill è di riutilizzare codice già scritto: Boost String Algorithm ha molti algoritmi per la manipolazione delle stringhe, incluso trim.

8

Nessun problema.

La stringa temporanea viene creata a ogni chiamata e automaticamente distrutta nuovamente alla fine dell'istruzione. Finché non si salva un riferimento (penzolante) ad esso, non ci sono problemi.

4

In generale, solo la nuova/malloc senza eliminazione/libero causerà la perdita di memoria. Nel tuo caso, nessun nuovo richiamo, quindi non dovrebbe esserci perdita di memoria. Il " \t\n\r" è nella memoria stack e riutilizzati ogni volta qui crea un'istanza per std::string &white_chars

L'istanza temporanea creata in pila e rilasciato dopo il ritorno funzione. non ci sono perdite di memoria.

+0

Come si spiega quindi il rapporto sulle perdite di memoria di valgrind? Indica che succede quando la stringa ha usato 'new' (althout in' string :: substr, ma la tua risposta non risolve nulla. – Shahbaz

+0

@Shahbaz: diagnosi errata? Valgrind è noto per aver segnalato problemi nell'STL, soprattutto io pensa perché l'allocatore STL "memorizza nella cache" alcuni blocchi di memoria per un successivo riutilizzo. –