如何修复在代码的某个部分引发的此异常

How do I fix this exception being thrown at a certain part of my code?

本文关键字:异常 何修复 代码 个部      更新时间:2023-10-16

当我构建代码时,我在输出窗口中没有收到任何错误。但是,在运行它之后,编译器会向我的代码抛出一个异常(我将在抛出它的位置发表评论(,说"引发异常:读取访问冲突。温度是0xCDCDCDCD。

尝试研究此错误是什么,我发现这是针对未分配的内存,但我看不到未分配的内容。

这是我的链表.cpp文件。异常将在此文件末尾的一行引发。

#include "linkedlist.h"
struct ll::node 
{
    weapons data;
    node* next;
};
ll::ll()
{
    head = NULL;
}
ll::~ll()
{
    while (head != NULL)
    {
        node* temp = head;
        head = head->next;
        delete temp;
    }
}
void ll::addItem(weapons obj)
{
    node* newNode = new node;
    node* temp = head;
    newNode->data = obj;
    if (head == NULL)
        head = newNode;
    return;
    while (temp->next != NULL)
    {
        temp = temp->next;
    }
    if (temp->next == NULL)
    {
        temp->next = newNode;
        return;
    }   
}
void ll::displayItems()
{
    for (node* temp = head; temp != NULL; temp = temp->next)
    {
            temp->data.getDescription(); //EXCEPTION THROWN HERE
    }
}

此文件具有继承的类"武器",该类是被称为"临时>数据"的对象。以及我在哪里有"得到描述"。

#include <vector>
using namespace std;
//base class
class inventory
{
protected:
    //number of items in inventory
    int mNumItems;
public:
    //getters
    void displayInv();
    int getNumItems();
    virtual void getDescription();
};
//weapon class
class weapons : public inventory
{
private:
    //name of object
    string mName;
    //what the object is
    string mInfo;
    //how much of the object
    int mAmount;
    //how much damage does it do
    double mDamage;
public:
    //constructor
    weapons();
    weapons(string, string, double, int);
    //getters
    string getName();
    void getDescription();
    int getAmount();
    double getDamage();
    string getInfo();
    //mutators
    void setAmount(int);
};

这就是我定义武器的地方

//weapon class
weapons::weapons()
{
    mName = " ";
    mInfo = " ";
    mDamage = 0.0;
    mAmount = 0;
}
weapons::weapons(string name, string info, double dmg, int amt)
{
    mName = name;
    mInfo = info;
    mDamage = dmg;
    mAmount = amt;
}
string weapons::getName()
{
    return mName;
}
int weapons::getAmount()
{
    return mAmount;
}
double weapons::getDamage()
{
    return mDamage;
}
string weapons::getInfo()
{
    return mInfo;
}
void weapons::getDescription()
{
    cout << getName() << ", " << getDamage() << " damage, " << getInfo() << " Amount: " << getAmount() << endl;
}
void weapons::setAmount(int amt)
{
    mAmount = amt;
}

如果我需要包含更多文件,请告诉我!

我得到了预期的结果,这是为了描述我在链表中的项目。不幸的是,我唯一的问题是这个异常被抛出。

问题

struct ll::node 
{
    weapons data;
    node* next;
};

void ll::addItem(weapons obj)
{
    node* newNode = new node; // leaks if node not added
    node* temp = head;
    newNode->data = obj;
    if (head == NULL)
        head = newNode;
    return; // this is a NASTY bug of a different sort. Most of the time 
            // the function will exit without doing ANYTHING
    while (temp->next != NULL)
    {
        temp = temp->next;
    }
    if (temp->next == NULL) // the only way out of the above loop is if 
                            // temp->next == NULL. This if is redundant.
    {
        temp->next = newNode;
        return;
    }   
}

没有什么能将newNode->next设置为安全值。这允许

    while (temp->next != NULL)
    {
        temp = temp->next;
    }

失败是因为无法保证temp->next永远NULL并且循环从列表的末尾前进。

溶液

强制next到安全值。

struct ll::node 
{
    weapons data;
    node* next = NULL;
};

或更通用的版本

struct ll::node 
{
    weapons data;
    node* next;
    node(const weapons & weap, // const reference eliminates a possible copy
         node * link = NULL): // if you know what the next link will be, 
                              // you can add it here. If not, it's always NULL
        data(weap),
        next(link) 
    {
    }    
};

addItem现在看起来像

void ll::addItem(const weapons & obj) 
{
    if (head == NULL)
    {
        head = new node(obj); // only making node if we need it
                              // less chance of leak
    }
    else
    {
        node * temp = head;
        while (temp->next != NULL)
        {
            temp = temp->next;
        }
        temp->next = newNode(obj);
    }
}

但是你可以在这里做一些非常偷偷摸摸的事情,让生活更轻松。 head实际上是另一个名称的next指针,所以如果你可以抽象出不同的名称......我们可以通过跟踪指向next的指针而不是指向node的指针。当您必须插入或删除项目时,这非常方便:您既有对相关节点的引用,也有对前一个节点中的插入点的引用。

void ll::addItem(const weapons & obj) 
{
    node ** temp = &head; // get pointer to insertion point
    while ((*temp) != NULL) // next node, including head, is not null
    {
        temp = &(*temp)->next; // get pointer to next insertion point
    }
    *temp = newNode(obj); // insert node
}

一半的代码。这如何帮助删除的示例:

void ll::removeItem(const weapons & obj) 
{
    node ** temp = &head; 
    while ((*temp) != NULL && (*temp)->data != obj) 
    {
        temp = &(*temp)->next; 
    }
    if  (*temp != NULL) // found it!
    {
        node * rem = *temp; // get node to remove so we don't lose it when we relink
        *temp = rem->next; // point at item after rem
        delete rem; // release item
    }
}