【问题标题】:possible memory leak when returning a string?返回字符串时可能存在内存泄漏?
【发布时间】:2013-01-12 06:51:51
【问题描述】:

我使用 valgrind --leak-check=full 检查我的程序,发现了一个我不知道的泄漏:

==6072== 54 bytes in 2 blocks are possibly lost in loss record 15 of 28
==6072==    at 0x4C2AF8E: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==6072==    by 0x55B63B8: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==6072==    by 0x55B7D94: char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==6072==    by 0x55B7E72: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.17)
==6072==    by 0x4268ED: Writable::readString(std::istream*) (Writable.cpp:33)

这是我的代码 sn-p:

#include "Writable.h"

Writable::Writable()
{
    //ctor
}

Writable::~Writable()
{
    //dtor
}


void Writable::writeString(ostream* ofs, string str){
    int length = str.size()+1;

    ofs->write((char*)&length, sizeof(length));

    if (length > 1)
        ofs->write(str.c_str(), length);

}

string Writable::readString(istream* ifs) {
    int length = 0;

    ifs->read((char*)&length, sizeof(length));

    if(length > 1) {
        char buf[length];
        ifs->read(buf, length);

        return string(buf);
    }

    return string("");
}

它指向“返回字符串(buf)”行。你能弄清楚那里的泄漏是如何发生的吗?

干杯

【问题讨论】:

  • 可变长度数组不是标准 C++ 的一部分。无论如何,返回一个std::string 就可以了,而且你不必在这样做的时候强制转换它。
  • 返回“普通”字符串时会得到什么? string Foo() { string bar = "Hello, World"; return bar; }
  • int length = 0; char buf[length]; 你怎么编译?
  • 请向我们展示您的真实代码。C++ 中不能有长度为 0 的数组。
  • @billz:假设大多数编译器通过编译器扩展支持 VLA,这可能会起作用。

标签: c++ memory memory-leaks


【解决方案1】:

好的,我不太确定你想在这里做什么。对于您的writeString 方法(如果它不使用任何成员,为什么它应该是一个方法?),您应该将流作为引用传递,并将您的字符串作为常量引用传递。您的代码可以简化为:

void Writable::writeString(std::ostream & ofs, std::string const & str){
    ofs << str;
}

如果标准已经为您做了这些,则无需自己摆弄指针和缓冲区。

至于您的readString“方法”:您似乎尝试读取4个字符(sizeof(length))并将它们存储在length中。如果您有 4 个字符,例如“abcd”,则您的 length 变量包含位模式 41424344(十六进制)。在十进制中,这是1094861636。基本上,然后您尝试从您的流中读取下十亿个字符(在您之前提取的abcd 之后)。您的流很可能不包含十亿个字符,因此您的缓冲区的很大一部分将未初始化。如果幸运的话,您会在某处发现终止流的 NULL 字符。

我不知道你是想读整个流还是只读一行。在后一种情况下,您可以将代码简化为:

std::string Writable::readString(std::ostream & ofs){
    std::string extracted;
    getline(ofs, extracted);
    return std::move(extracted); // or return extracted; if you have a pre C++11 compiler
}

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-14
    • 2013-09-05
    • 2019-07-17
    • 2014-04-30
    • 2021-11-01
    • 2021-01-26
    • 2011-08-29
    • 2013-04-03
    相关资源
    最近更新 更多