这个Valgrind错误的原因是什么?

6

Valgrind报告了一个substr函数的问题。

string Message::nextField(string& input) {
    int posSeparator = input.find_first_of(SEPARATOR);
    string temp;
    temp = input.substr(0, posSeparator); //Error points to this line
    input.erase(0, posSeparator + 1);
    return temp;
}

错误信息如下:
在 1 of 1 的损失记录中,12 个块中的 290 字节肯定已经丢失。
这个函数的作用基本上是解析输入,返回由 SEPARATOR 字符分隔的字符串部分。该函数从另一个类的方法中调用,其定义如下:
void doSomething(string input) {
    input.erase(0,2);
    string temp = nextField(input);
    this->room = atoi(temp.c_str());
    temp = input;
    this->money = atoi(temp.c_str());
}

这里没有其他奇怪或重要到足以被包含的东西。 我使用Eclipse Indigo的Valgrind分析中默认设置的Valgrind配置。 有什么想法吗?


3
你在编译时进行了优化吗?如果是,不要这样做。这样会导致Valgrind产生许多虚假报告。 - David Hammen
你可以尝试使用 string temp = input.substr(0, posSeparator); 来初始化字符串,而不是赋值。虽然这与你的问题似乎没有直接关系。 - Jonathan Leffler
你的程序以受控方式退出(例如通过从主函数返回),还是仅调用exit()(或更糟的_exit())?我发现,如果您希望valgrind有关泄漏内存方面的错误提示有所帮助,最好确保您的程序通过从main()正常返回来退出,否则某些东西就不会被释放,这在实际情况下是可以接受的(因为操作系统将自动释放进程的所有内存),但valgrind会将其视为泄漏。 - Jeremy Friesner
2
你没有检查posSeparator是否实际上与string::npos不同 - 这可能会在erase中引起问题。这是一个猜测,但它可能会修复一个错误。 - thiton
@thiton 谢谢,那就是问题所在。回答它,否则我会回答的。 - Guido Tarsia
显示剩余3条评论
3个回答

2
这可能不是你代码中的错误。这个错误可能是由于C++标准库实现细节而导致的。为了验证这一点,请尝试从Valgrind FAQ中执行以下操作:

对于GCC 2.91、2.95、3.0和3.1,使用-STL编译所有源文件,并使用-D__USE_MALLOC选项。注意!这在GCC 3.3版本开始被移除。

对于GCC 3.2.2及更高版本,在运行程序之前,应该导出环境变量GLIBCPP_FORCE_NEW。

对于GCC 3.4及更高版本,该变量的名称已更改为GLIBCXX_FORCE_NEW。


1
你的源代码可能在其他地方存在错误。我尝试使用以下代码复制这个错误:
#include <string>
#include <iostream>
#include <cstdlib>

using namespace std;

const char SEPARATOR = ':';

struct Foo
{
public:
    int room;
    int money;

    void doSomething(string input) {
        input.erase(0,2);
        string temp = nextField(input);
        this->room = atoi(temp.c_str());
        temp = input;
        this->money = atoi(temp.c_str());
    }

    string nextField(string& input) {
        int posSeparator = input.find_first_of(SEPARATOR);
        string temp;
        temp = input.substr(0, posSeparator); //Error points to this line
        input.erase(0, posSeparator + 1);
        return temp;
    }
};

int main()
{
    Foo f;
    f.doSomething("--234:12");
    std::cout << f.room << " - " << f.money << std::endl;
}

然后我运行了Valgrind:

valgrind --tool=memcheck <executable>

输出结果为:

HEAP SUMMARY:
    in use at exit: 0 bytes in 0 blocks
  total heap usage: 2 allocs, 2 frees, 61 bytes allocated

All heap blocks were freed -- no leaks are possible

For counts of detected and suppressed errors, rerun with: -v
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 4 from 4)

所以,你的问题可能不在这段代码中


0

你没有检查posSeparator是否实际上与string::npos不同 - 这可能会在erase中引起问题。这只是一个猜测,但它可能会修复一个错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接