【问题标题】:Exception thrown: write access violation (this->tail was nullptr)抛出异常:写访问冲突(this->tail was nullptr)
【发布时间】:2018-10-11 05:46:12
【问题描述】:

我已经编译了我的代码,它似乎可以正常工作。但是我不知从哪里得到了错误(this->tail 是 nullptr)。我尝试过更改新节点的创建。但似乎没有任何效果。我不知道哪里 tail 被设置为 nullptr 并弄乱了代码。

我将如何解决这个问题?有没有办法在不破坏所有其他功能的情况下将 tail 设置为非 nullptr?我对异常抛出不太熟悉,所以如果你能解释一下情况会很有帮助。

#ifndef MYDLL_H
#define MYDLL_H

#include <iostream>
#include <new>
using namespace std;

class MyDLL
{
    struct Node
{
    int i;
    Node* next;
    Node* prev;
};

Node* head;
Node* tail;

public:
MyDLL();
~MyDLL();
void append(int);
void remove(int);
bool find(int) const;
void clear();
void print() const;
void reverse() const;
};

MyDLL::MyDLL()
{
head = nullptr;
tail = nullptr;
}
MyDLL::~MyDLL()
{
clear();
}

void MyDLL::append(int i)
{
    Node *n = new Node{ i, nullptr, nullptr };
if (head = nullptr)
{
    head = n;
    tail = n;
}
else
{
    n->prev = tail;
    tail->next = n; **<--- This is where the exception thrown error is showing up**
    tail = n;
}
}

void MyDLL::remove(int i)
{
Node* p = head;
Node* q = tail;

while (p != nullptr && p->i != i)
{
    q = p;
    p = p->next;
}

if (p = nullptr)
{
    return;
}

if (q = nullptr)
{
    head = p->next;
}
else
{
    q->next = p->next;
}

if (p->next = 0)
{
    tail = q;
}
else
{
    p->next->prev = q;
}
delete(p);
}

bool MyDLL::find(int i) const
{
Node* p = tail;

while (p != nullptr)
{
    if (p->i = i)
    {
        return (true);
    }
    p = p->prev;
}
return (false);
}

void MyDLL::clear()
{
while (tail != nullptr)
{
    Node* p = tail;
    tail = p->prev;
    delete (p);
}
head = nullptr;
}

void MyDLL::print() const
{
Node* p = head;

while (p)
{
    cout << p->i << "\t";
    p = p->next;
}
cout << "\n";
}

void MyDLL::reverse() const
{
Node* p = tail;

while (p)
{
    cout << p->i << "\t";
    p = p->prev;
}
cout << "\n";
}
#endif

int main()
{
    MyDLL list;
list.append(5);
list.append(6);
list.append(7);
list.append(8);

list.print();
list.reverse();
cout << system("pause");
}

【问题讨论】:

  • 这里有一个更容易发现和解决问题的技巧:一步一步做每一件事。采取一些小的步骤,只实现一小部分代码,并在继续下一步之前对其进行全面测试以确保它可以正常工作。这样一来,查明何时何地将错误引入代码并解决它们将变得更加容易。 Some related reading.
  • 我也建议你花点时间做一些rubber duck debugging。向你的(真实的或想象的)“橡皮鸭”(或者如果你找不到橡皮鸭的朋友)详细解释你的代码,每一行。当然,这需要您知道例如之间的区别。使用= 进行赋值并与== 进行相等性比较。
  • 附带说明:您应该使用清晰的变量名称,例如为什么在remove 中不使用Node* headNode = head; Node* tailNode = tail; 而不是Node* p = head; Node* q = tail;

标签: c++ exception linked-list access-violation throw


【解决方案1】:

这段代码正是您要使用nullptr = tail 而不是tail = nullptr 的原因。特别是,每次您“检查”tail 是否为空指针时,您都将 nullptr 分配给 tail,然后分配运算符返回一个值,该值然后隐式转换为布尔值,不会出现错误。但错误实际上是存在的。执行比较时将“=”运算符替换为“==”,除非您确实有理由分配和检查返回值。

【讨论】:

    【解决方案2】:

    请在您的代码中使用 == 修复 =

    void MyDLL::append(int i)
    {
        Node *n = new Node{ i, nullptr, nullptr };
        if (head == nullptr)
    

    总是建议像反向比较(nullptr == head)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 2020-04-15
      • 2016-08-25
      • 2022-12-20
      • 2021-11-27
      • 2020-09-12
      • 2021-07-12
      • 1970-01-01
      相关资源
      最近更新 更多