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 告诉我“块肯定丢失了”的内存泄漏,但这是一个不太确定的消息。

所以问题就变成了,我是否通过将默认值分配给 a 导致内存泄漏std::string &?如果是这样,我做错了什么?

4

3 回答 3

13

没有技术问题,但是std::string在每次通话时从哲学上创建一个临时的并不是那么好。特别是对于 libstdc++(您似乎在使用),因为它每次都会导致内存分配(缺乏短字符串优化)。

由于find_first_not_of具有采用 a 的重载char const*,因此最好提供两个重载:

// 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 回答