如何解决在代码的特定部分抛出的异常?

时间:2019-04-20 21:40:04

标签: c++

构建代码时,在输出窗口中没有任何错误。但是,在运行它之后,编译器在我的代码中抛出一个异常(我将在抛出该异常的位置进行注释),并说“抛出异常:读取访问冲突。 temp为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
    }
}

此文件具有继承的类“武器”,该类被称为“临时->数据”。以及我有“ getDescription”的地方。

#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;
}

让我知道是否需要添加其他文件!

我得到了预期的结果,因为它可以描述我在链接列表中拥有的项目。不幸的是,我唯一的问题是引发了该异常。

1 个答案:

答案 0 :(得分:2)

问题

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的指针而不是指向{{ 1}}。当您必须插入或删除项目时,这确实非常方便:您既可以参考所讨论的节点,也可以参考先前节点中的插入点。

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
}