我通过以下主要功能遇到细分错误。 头文件具有一个链表实现,其中包含一个迭代器类和不同的测试成员。
问题是分段错误错误出现在某些编译器上,而在其他编译器上消失了。我尝试使用GDB调试任何错误,但程序执行正常。
这真的让我很烦,因为我找不到引起分段错误的原因。
非常感谢您的帮助。
编辑: 我注意到,使用此更新的main,逻辑存在缺陷,并且不会在指定位置插入节点。因此,我将不得不进行更多调试才能找出问题所在。
似乎执行了else if
中的insert()
块而不是else
块。
Main.cpp
#include <iostream>
#include "List.h"
int main(){
List<double> l;
l.push_back(1.1);
l.push_back(2.2);
l.insert(l.begin()++, 3.3);
l.printList();
}
List.h
#include <cstdint>
#include <iostream>
#include <memory>
template<typename T>
class List
{
public:
class Node {
public:
Node(T value) : value_(value) {}
Node(T value, Node* prev, Node* next) : value_(value), prev_(prev), next_(next) {}
T value_;
Node* next_;
Node* prev_;
};
Node* head_;
Node* tail_;
//! An iterator over the list
class iterator
{
public:
Node* iNode;
iterator(Node* head): iNode(head){ }
~iterator() {}
T& operator*() {
return iNode -> value_;
}
iterator& operator++() {
iNode = iNode->next_;
return *this;
}
iterator operator++(int ignored) {
iNode = iNode->next_;
return *this;
}
iterator& operator--() {
iNode = iNode->prev_;
return *this;
}
//! Is this iterator pointing at the same place as another one?
bool operator== (const iterator& it) const {
return this->iNode == it.iNode;
}
//! Is this iterator pointing at a different place from another?
bool operator!= (const iterator& it) const {
return this->iNode != it.iNode;
}
};
//! Default constructor
List() :tail_(nullptr) {}
void push_back_node(T value)
{
Node* newnode = new Node(value, tail_, nullptr); //make and link new tail node
if (tail_)
{
tail_->next_ = newnode; // link in new node
}
else
{
head_ = newnode;
}
tail_ = newnode; // update tail
}
//! Copy constructor
List(const List& lst) : head_(nullptr), tail_(nullptr)
{
Node* cur = lst.head_; //get first source item.
while (cur) // if there is a source item to copy
{
push_back_node(cur->value_); // stick the item on the end of this list
cur = cur->next_; // get next source item
}
}
void clear()
{
while (head_)
{
delete std::exchange(head_, head_->next_);
}
tail_ = head_;
}
//! Copy assignment operator
List& operator= (const List& list_copy) {
List tmp(list_copy);
clear();
std::swap(*this, tmp);
return *this;
}
//! Move constructor
List(List&& move) {
head_ = std::move(move.head_);
tail_ = std::move(move.tail_);
}
////! Move assignment operator
List& operator= (List&& list) {
head_ = std::move(list.head_);
tail_ = std::move(list.tail_);
return *this;
}
//! Destructor
~List() {}
//
// Accessors:
//
//! How many elements are in this list?
size_t size() const {
size_t size = 0;
auto temp = head_;
while (temp != nullptr)
{
size++;
temp = temp->next_;
}
return size;
}
//! Is this list empty?
bool empty() const {
return tail_ == nullptr && head_ == nullptr;
}
//! Get an iterator to the beginning of the list
iterator begin() {
return List<T>::iterator(head_);
}
//! Get an iterator just past the end of the list
iterator end() {
return List<T>::iterator(tail_);
}
//
// Mutators:
//
//! Copy an element to the front of the list
void push_front(const T& value) {
Node* node = new Node(value);
if (head_ == nullptr) {
head_ = node;
}
else {
node->next_ = head_;
head_ = node;
}
}
//! Move an element to the front of the list
void push_front(T&& value) {
Node* node = new Node(value);
if (head_ == nullptr) {
head_ = node;
}
else {
node->next_ = head_;
head_ = node;
}
}
//! Copy an element to the back of the list
void push_back(const T& value) {
Node* node = new Node(value);
if (tail_) {
tail_->next_ = node;
tail_ = tail_->next_;
}
else {
head_ = node;
tail_ = head_;
}
}
//! Add an element to the back of the list
void push_back(T&& value) {
Node* node = new Node(value);
if (tail_) {
tail_->next_ = node;
tail_ = tail_->next_;
}
else {
head_ = node;
tail_ = head_;
}
}
iterator insert(iterator position, const T& value) {
Node* newNode = new Node(value);
if (position == List<T>::iterator(head_)) {
newNode->next_ = head_;
head_ = newNode;
}
else if (!position.iNode->next_) {
position.iNode->next_ = newNode;
}
else {
Node* curr = head_;
while (curr->next_ != position.iNode)
{
curr = curr->next_;
}
newNode->next_ = curr->next_;
curr->next_ = newNode;
}
return position;
}
void printList() const{
auto node = head_;
while (node != nullptr)
{
std::cout << node -> value_ << " ";
node = node->next_;
}
}
iterator insert(iterator position, T&& value){
Node* newNode = new Node(value);
if (position == List<T>::iterator(head_)) {
newNode->next_ = head_;
head_ = newNode;
}
else if (!position.iNode->next_) {
position.iNode->next_ = newNode;
}
else {
Node* curr = head_;
while (curr->next_ != position.iNode)
{
curr = curr->next_;
}
newNode->next_ = curr->next_;
curr->next_ = newNode;
}
return position;
}
//! Remove an element from an arbitrary location
void erase(iterator it) {
Node* temp = it.iNode->next_;
// Copy data of the next node to current node
it.iNode->value_ = it.iNode->next_->value_;
// Perform conventional deletion
it.iNode->next_ = it.iNode->next_->next_;
free(temp);
}
};
答案 0 :(得分:1)
Node(T value) : value_(value) {}
没有将prev_
或next_
指向有用的地方,所以
Node* node = new Node(value);
会生成一个定时炸弹节点,除非您稍后将其prev_
和next_
成员设置为指向安全的地方。 push_back
不会这样做。
解决方案:
使用
Node(T value, Node* prev, Node* next) : value_(value), prev_(prev), next_(next) {}
相反:
Node* node = new Node(value, nullptr, nullptr);
您将在push_back
,push_front
和insert
的所有变体中发现类似的缺陷。您还可以使用Node(T value, Node* prev, Node* next)
构造函数来简化一些添加,推送和插入节点的工作,方法是使用周围的节点代替nullptr