14

次のように宣言されたメソッドがあります。

/*!
\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");

メソッドの定義は面白くありませんが、とにかく次のとおりです。

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

現在、このメソッドのほとんどの使用法では、最初の引数のみを指定しています。Valgrind から次の警告が表示されます

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

「ブロックが失われる可能性がある」ことに注意してください。Valgrind が「ブロックが確実に失われている」と言うメモリ リークを見たことがありますが、これはあまり確実なメッセージではありません。

したがって、問題は、デフォルト値をに割り当てることでメモリリークを引き起こしているのstd::string &でしょうか? もしそうなら、私は何を間違っていますか?

4

3 に答える 3

13

技術的な問題はありませんが、哲学的std::stringに各呼び出しで一時的なものを作成するのはあまり良くありません。特にlibstdc ++(使用しているように見える)では、毎回メモリ割り当てが発生するため(短い文字列の最適化がないため)。

find_first_not_ofを受け取るオーバーロードがあるため、char const*代わりに 2 つのオーバーロードを提供することをお勧めします。

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

これは、呼び出し時Trim(xx, "abc")に一時的な生成が回避されることも意味しますstd::string:)

もちろん、やり過ぎの解決策は、既に作成されたコードを再利用することです。Boost String Algorithmには、trim.

于 2012-05-25T07:50:19.433 に答える
8

問題ない。

一時文字列は呼び出しごとに作成され、ステートメントの最後で自動的に破棄されます。(ぶら下がっている)参照を保存しない限り、問題はありません。

于 2012-05-25T07:36:38.317 に答える
4

一般に、delete/freeのないnew/mallocのみがメモリリークを引き起こします。あなたの場合、新しい呼び出しはないので、メモリリークはありません。は" \t\n\r"スタックメモリにあり、インスタンスを作成するために毎回再利用されますstd::string &white_chars

スタックに作成され、関数の戻り後に解放される一時インスタンス。メモリリークもありません。

于 2012-05-25T07:44:26.157 に答える