3

我目前正在调试一个相当大的程序。当我来到以下代码行时:

value->binary_string = value_it->binary_string.substr(range->msb->value, range->size);

该程序的行为不正确。这里的 value 是一个指向结构的指针,该结构的成员名为 binary_string,类型为 std::string。当我在调试时到达这一行时,我看到:

value_it->binary_string = "00000000000000000000000000000111"
range->msb->value = 0
range->size = 32

这行代码执行后,value->binary_string为空!我什至将线路更改为

value->binary_string = value_it->binary_string

它仍然失败!

当我在调试时到达这条线时,我的程序正在使用大约 100 Mb 的内存,所以我认为这不是内存问题(尽管我正在运行 Valgrind 以验证这一点)。我正在使用 Ubuntu 11.10、g++-4.6 和 libstdc++6。

有没有人遇到过这样的事情?我不知道为什么我的琴弦不起作用!

谢谢,

山姆

编辑1:

值的类型是 NumberInst,定义如下:

typedef std::string String;

struct NumberInst
{
    unsigned size;
    bool signed_;
    String binary_string;
    bool valid;
    unsigned value;

    NumberInst();
};

编辑2:

看起来我已经缩小了搜索范围。在调试时,我尝试了一些打印命令:

print value_it->binary_string
"00000000000000000000000000000111"
print value_it->binary_string[31]
'1'
print value_it->binary_string.substr(0, String::npos)
""
print value_it->binary_string.substr(0, 1)
""

在这种情况下,似乎 substr 无法正常工作。但是,当我在 main 函数中测试 substr 时,它似乎工作正常。

4

2 回答 2

2

我发现当这种“奇怪”的事情发生时,通常有两个常见的原因:

  1. 你犯了一个简单的错误,只是忽略了它。
  2. 某种内存损坏。

要检查第一个原因,请仔细阅读有问题的代码,并有意识地决定阅读代码正在做什么,而不是你认为它应该做什么。通过假设代码应该做一些实际上没有做的事情,很容易忽略明显的错误,尤其是在你已经查看了一段时间的代码中。例如,几个月前,我正在调试一些东西,并且遇到了一个变量“神奇地”突然改变其值的问题。原来我只是打印了错误的变量(呃!),如果我一直在阅读代码实际所说的内容,我会更快地发现这一点。

内存损坏是一种更难找到的野兽,因为它可能发生在问题出现之前任何时间运行的任何代码中。Valgrind 不保证找到所有形式的损坏,请参阅此问题以获取示例。在调试模式下运行,设置内存观察点(如果您知道损坏总是发生在哪里)和其他与内存相关的工具可能会有所帮助,因为这会将问题减少到最小形式......在损坏之前不断消除正在运行的代码不会发生。

于 2012-03-01T23:01:36.340 回答
1

这个问题是由一个非常微妙的错误引起的。在我的项目中的某个地方:

NumberInst* number = new NumberInst;
number->binary_string.reserve(size);
for (unsigned i = 0; i < size; i++)
    number->binary_string[i] = ...;

不会抛出 std::out_of_range 异常,因为我假设标准库将数组索引与字符串的容量(而不是字符串的大小)进行比较。在调试器中调用 print 会成功,因为它可能会遍历缓冲区,直到到达 '\0' 字符。然而

String str = number->binary_string

将失败,因为标准库可能会从 [0, size) 复制 value_it->binary_string 的缓冲区并添加 '\0' 字符。由于 value_it->binary_string 的大小为 0,因此复制其内容将失败(substr 和其他依赖于调用字符串大小的函数也会失败)。

换句话说,问题是由调用引起的

str.reserve(size);

代替

str.resize(size);

谢谢大家的帮助!

山姆

于 2012-03-02T17:01:57.583 回答