2012-05-25 17 views
14

he un método declarado como tal:Si especifico un valor predeterminado para un argumento de tipo "std :: string &" en C++, ¿podría causar una pérdida de 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 definición del método es poco interesante, pero aquí está de todos modos:

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

Ahora bien, en la mayoría de los usos de este método, que suministran sólo el primer argumento Valgrind me da la siguiente advertencia

==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 "posiblemente se pierdan los bloques"? He visto pérdidas de memoria en las que Valgrind me dice "definitivamente se pierden bloques", pero este es un mensaje menos cierto.

Entonces la pregunta es: ¿estoy causando una pérdida de memoria asignando un valor predeterminado a std::string &? Si es así, ¿qué estoy haciendo mal?

Respuesta

13

No hay ningún problema técnico, pero filosóficamente la creación de un std::string temporal en cada llamada no es tan agradable. Especialmente con libstdC++ (que pareces usar) ya que causa una asignación de memoria cada vez (falta de optimización de cadena corta).

Desde find_first_not_of tiene una sobrecarga de tomar una char const*, que sería mejor para proporcionar dos sobrecargas en su lugar:

// 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); 

Esto también significa que cuando se llama a Trim(xx, "abc") se evitará el temporal std::string está generando :)

Por supuesto, la solución de overkill es reutilizar el código ya escrito: Boost String Algorithm tiene muchos algoritmos para la manipulación de cadenas, incluido trim.

8

No hay problema.

La cadena temporal se construye en cada llamada y se destruye automáticamente de nuevo al final de la instrucción. Siempre que no guarde una referencia (colgante), no hay problema.

4

En general, solo el nuevo/malloc sin eliminar/libre causará la pérdida de memoria. En su caso, no hay llamadas nuevas, por lo que no debería haber pérdida de memoria. El " \t\n\r" es en memoria de pila y volver a utilizar cada vez en un cajón de instancia para std::string &white_chars

La instancia temporal creado en pila y ser puesto en libertad después de retorno de la función. no hay pérdida de memoria también.

+0

¿Cómo se explica el informe de fuga de memoria de valgrind? Indica que sucede cuando string ha usado 'new' (aunque en' string :: substr, pero aun así su respuesta no resuelve nada. – Shahbaz

+0

@Shahbaz: misdiagnosis? Valgrind es bien conocido por informar problemas en el STL, sobre todo yo pensar porque el asignador STL "almacena en caché" algunos bloques de memoria para su posterior reutilización. –

Cuestiones relacionadas