我正在调试一个相当大的程序。当我来到以下代码行时:
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.
以前有没有人遇到这样的事情?我不知道为什么我的琴弦不起作用!
谢谢,
萨姆
EDIT1:
值的类型是NumberInst,定义如下:
typedef std::string String;
struct NumberInst
{
unsigned size;
bool signed_;
String binary_string;
bool valid;
unsigned value;
NumberInst();
};
EDIT2:
看起来我已经缩小了搜索范围。在调试时,我尝试了一些打印命令:
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无法正常工作。但是,当我在我的主函数中测试substr时,似乎工作正常。
答案 0 :(得分:2)
我发现,当发生类似“奇怪”的事情时,通常有两个常见的原因:
要检查第一个原因,请仔细阅读有问题的代码,并有意识地决定阅读代码正在做什么,而不是您认为应该做什么。通过假设代码应该执行实际上没有做的事情,很容易忽略明显的错误,特别是在你已经看了一段时间的代码中。例如,几个月前我正在调试一些问题,并且一个变量“神奇地”突然改变它的值。事实证明我只是打印了错误的变量(呃!)如果我一直在阅读代码实际上所说的内容,我会更快地抓住它。
内存损坏是一个更难找到的野兽,因为它可能发生在问题出现之前的任何时间运行的任何代码中。 Valgrind不保证找到所有形式的腐败,请参阅this question作为示例。在调试模式下运行,设置内存监视点(如果你知道腐败始终发生在哪里)和其他与内存相关的工具可能会有所帮助,因为它会将问题减少到最小的形式...继续消除代码运行一点点,直到腐败不会发生。
答案 1 :(得分: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-&gt; binary_string的缓冲区并添加'\ 0'字符。由于value_it-&gt; binary_string的大小为0,因此复制其内容将失败(与substr和依赖于调用字符串大小的其他函数一样)。
换句话说,问题是由调用
引起的str.reserve(size);
而不是
str.resize(size);
感谢大家的帮助!
萨姆