我正在编写一些简单的连接组件代码,并遇到了一个奇怪的片段错误。
我的代码如下:先给出一些定义。
Node* node;
typedef std::pair<int, Node*> Edge;
struct Node {
...
std::list<Edge> neighbors;
...
}
分段错误的代码如下:
if (node->neighbors.empty())
{
node->label = label_set.make();
}
else
{
Node* first_neighbor = node->neighbors.front().second;
node->label = first_neighbor->label;
int i = 0;
for (list<Edge>::iterator it = node->neighbors.begin(); it != node->neighbors.end(); it++)
{
i ++;
Node* n2 = (Node*)it->second;
node->label = label_set.merge(node->label, n2->label);
}
}
真正奇怪的一点是以下几点:
(lldb) p node->neighbors
(std::list<std::pair<int, _Node *>, std::allocator<std::pair<int, _Node *> > >) $4 = size=1 {
[0] = {
first = 78
second = 0x00d85520
}
}
(lldb) p *it
(std::pair<int, _Node *>) $8 = {
first = 0
second = 0xa0a45254
}
(lldb) p n2
(Node *) $5 = 0xa0a45254
看到这个,我明白了分段的错误。n2
被设置为一个完全奇怪的值。它不在列表中;我是否没有正确地迭代列表?n2
是否被随机数据填充,因为它超出了列表的范围?但是,我的迭代是如何摆脱界限的呢?我太笨了。
编辑:,我肯定在列表范围之外:在段错误i == 3
时。
EDIT2是否与我跟踪节点的方式有关?
发布于 2014-09-29 17:10:24
以下可能是正在发生的情况:
如果您确实注释掉了调用label_set.merge
的for循环中的最后一行,那么只剩下一个简单的循环,这个循环应该从std::list
的开头一直到末尾。
增量是存在的(尽管执行++it
更好,但这是另一回事),再加上在循环中所做的一切都是检索it->second
。然而,正如您所声称的那样,您的循环将永远运行。
由于是这种情况,一个结论是node
无效,或者node->neighbors
无效。您需要检查您的代码,以确保您没有错误地管理内存或指针。使用智能指针也比使用原始指针更好(甚至可以使用
std::pair<int, std::shared_ptr<Node>>
如果节点指针确实在各个对象之间共享)。
至于调试器,您可以在无效的对象中拥有看起来很好的值。可能发生的情况是,调试器正在向您显示无效对象中各个成员的值。由于对象无效,这些值可以是任何值,包括合理的外观值。
编辑:
你在这里发布的链接:https://gist.github.com/noio/3082a0f351edb1821e90
显示获取vector<Node>
中最后一项的地址。这是危险的,如果向量调整到一个更大的容量,因为向量的迭代器将失效。不要持有指向向量内数据的指针值,除非可以保证在使用指针时不会调整矢量的大小。
发布于 2014-09-29 16:45:58
最好的猜测是,对label_set.merge
的调用从
node->neighbors
列表,使it
迭代器无效。当它返回时,您尝试增加迭代器以继续循环,但是由于它已经失效(可能现在指向已释放的内存),它就会进入永不停歇的状态。
由于您没有展示label_set
是什么或者merge
是如何工作的,所以不可能知道。
另一种可能是,您已经以某种方式破坏了堆,并以任意裁剪要覆盖的内容的方式使指针在周围悬空。尝试使用缬磨运行,看看它是否能告诉您更多的错误。
https://stackoverflow.com/questions/26104307
复制相似问题