带有圆形链接列表的崩溃
Crash with circular linked list
我正在尝试实现一个链接列表(我相信这是一个圆形链接列表),但是在使用它后,它最终会崩溃。我认为这是因为我使用的遍历指针无法正确设置为0,最终删除并表现出不确定的行为。
感谢您的帮助。
这是我正在使用的功能:
struct records t_head = 0;
struct records* find_id(Rect a)
{
struct records* tmp;
struct records* prev;
// Add first node
if (t_head == NULL) {
tmp = new records;
tmp->b = a;
tmp->id = trecord_count + 1;
tmp->tally.resize(labelsInfo.size());
tmp->frames = 0;
t_head = tmp;
t_head->next = NULL;
trecord_count++;
}
else {
// Check if there is any node that has delete_flag set first
tmp = t_head;
while (tmp) {
if (delete_flag) {
// Delete here
if (tmp == t_head) {
t_head = tmp->next;
delete (tmp);
trecord_count--;
}
else {
prev->next = tmp->next;
delete (tmp);
trecord_count--;
}
}
prev = tmp;
tmp = tmp->next;
}
tmp = new records;
tmp->b = a;
tmp->id = trecord_count + 1;
tmp->tally.resize(labelsInfo.size());
tmp->frames = 0;
tmp->next = t_head;
t_head = tmp;
trecord_count++;
}
return tmp;
}
结构定义是:
struct records {
int id;
Rect b;
vector<int> tally= {};
int frames=0;
int delete_flag=0;
struct records *next;
};
以下代码运行,但它在评论中已经提到的这些都显示了缺陷。
- 在您的版本中,您访问
tmp
中的指针,您刚刚在循环中删除了使用SETdelete_flag
搜索记录。这在以下版本中得到了纠正。所需的修改用//< Tobias
标记。请注意,您可以在Linux下轻松发现此类错误。安登·科尔曼(Andon M. Coleman)也在他的评论中提到了这一点。 - 在您的
find_id
版本中,实际上没有搜索已实现的a
。我已经在我的版本中实现了这样的搜索。 - 如果您在列表中间删除了一些记录,则最终记录保留其ID,但您降低
trecord_count
并再次分配相同的ID。因此,您最终获得了具有相同ID的多个记录。
编辑:我在程序中添加了一些日志记录。也许,这可以帮助您了解发生了什么。此外,我将frames
滥用为真正的id
。即,没有两个记录具有相同的 frames
-value。记录在括号中,完整列表在方括号中。否您没有圆形列表。也许,您会得到错误的印象,因为您在正面添加了新记录,因此,您需要将t_head
的旧值用作新创建的记录的next
的值。
程序的输出为:
g++ -std=c++11 -g -O0 ./test.cc -o a.exe && ./a.exe
Returning { frames=1 id=1 b=1 }
Full content:
[ { frames=1 id=1 b=1 } ]
Adding { frames=2 id=2 b=2 }
Returning { frames=2 id=2 b=2 }
Full content:
[ { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
Adding { frames=3 id=3 b=3 }
Returning { frames=3 id=3 b=3 }
Full content:
[ { frames=3 id=3 b=3 }, { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
Deleting head { frames=3 id=3 b=3 }
Adding { frames=4 id=3 b=4 }
Returning { frames=4 id=3 b=4 }
Full content:
[ { frames=4 id=3 b=4 }, { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
Returning { frames=2 id=2 b=2 }
Full content:
[ { frames=4 id=3 b=4 }, { frames=2 id=2 b=2 }, { frames=1 id=1 b=1 } ]
Deleting { frames=2 id=2 b=2 }
Adding { frames=5 id=3 b=5 }
Returning { frames=5 id=3 b=5 }
Full content:
[ { frames=5 id=3 b=5 }, { frames=4 id=3 b=4 }, { frames=1 id=1 b=1 } ]
At exit: [ { frames=5 id=3 b=5 }, { frames=4 id=3 b=4 }, { frames=1 id=1 b=1 } ]
遵循名为 test.cc
的程序:
#include <vector>
#include <iostream>
#include <cstdlib>
typedef int Rect;
struct records {
int id;
Rect b;
std::vector<int> tally= {};
int frames=0;
int delete_flag=0;
struct records *next;
};
struct records *t_head = 0;
int trecord_count = 0;
int trecord_frames = 0;
std::ostream& operator << (std::ostream& os, const records& r) {
os << "{ frames=" << r.frames << " id=" << r.id << " b=" << r.b << " }";
return os;
}
std::ostream& operator << (std::ostream& os, const records* r) {
os << "[ ";
if(r)
os << *r;
for(r=r->next; r; r=r->next)
std::cout << ", " << *r;
std::cout << " ]n";
}
struct records* find_id(Rect a)
{
struct records* tmp;
struct records* prev;
// Add first node
if (t_head == NULL) {
tmp = new records;
tmp->b = a;
tmp->id = trecord_count + 1;
tmp->tally.resize(0);
tmp->frames = ++trecord_frames;
t_head = tmp;
t_head->next = NULL;
trecord_count++;
}
else {
// Check if there is any node that has delete_flag set first
tmp = t_head;
while (tmp) {
if (tmp->delete_flag) {
// Delete here
if (tmp == t_head) {
std::cout << "Deleting head " << *tmp << std::endl;
t_head = tmp->next;
delete (tmp);
trecord_count--;
tmp = t_head; //< Tobias
}
else {
std::cout << "Deleting " << *tmp << std::endl;
prev->next = tmp->next;
delete (tmp);
trecord_count--;
tmp = prev->next; //< Tobias
}
} else {
prev = tmp;
tmp = tmp->next;
}
}
// Search for the id
tmp = t_head;
while(tmp && (tmp->b != a))
tmp = tmp->next;
if(!tmp) {
tmp = new records;
tmp->b = a;
tmp->id = trecord_count + 1;
tmp->tally.resize(0);
tmp->frames = ++trecord_frames;
tmp->next = t_head;
t_head = tmp;
std::cout << "Adding " << *tmp << std::endl;
trecord_count++;
}
}
std::cout << "Returning " << *tmp << std::endl;
std::cout << "Full content:n" << t_head << std::endl;
return tmp;
}
int main() {
find_id(1);
find_id(2);
find_id(3);
t_head->delete_flag=1;
find_id(4);
records* r = find_id(2);
r->delete_flag = 1;
find_id(5);
std::cout << "nAt exit: " << t_head;
return 0;
}
/*
Local Variables:
compile-command: "g++ -std=c++11 -g -O0 ./test.cc -o a.exe && ./a.exe"
End:
*/
相关文章:
- 当回溯以零开始时,如何调试崩溃
- 为什么它只打印双链接列表的第一个值,而我的程序却崩溃了
- 如何在C / C++中正确实现链接列表而不会使程序崩溃
- C 链接列表堆栈POP功能崩溃
- 我很难弄清楚为什么我的双重链接列表会崩溃,我可以找到一些方向
- 将元素添加到列表会使程序崩溃..有时
- C++初始化复制构造函数中的列表赋值,并在复制构造函数中崩溃
- 带有圆形链接列表的崩溃
- 删除 C++ 中的列表会导致崩溃
- 每次我在SFML中绘制列表项时,它都会崩溃
- Qt 当列表小部件项被单击两次时崩溃
- 复制列表时光荣崩溃
- 使用"pop_front"从排序列表中删除元素会导致崩溃
- C++STL列表崩溃,数字超过1000 000 000 000
- 当列表中有两个以上的项目时,链表的函数 add 会崩溃
- 应用程序在OpenCV的均衡化列表上崩溃
- 当添加一个指针到多个boost::ptr_vector列表时崩溃
- 删除循环列表中的节点时崩溃
- 复制链接列表会使程序崩溃
- 排序算法在试图打印列表信息时崩溃