简体   繁体   English

C++:如何纠正我的代码的读取访问冲突

[英]C++: How do I correct the read access violation that my code does

I am beginner at C++ and have been trying to figure a few things out on my own.我是 C++ 的初学者,并且一直在尝试自己解决一些问题。 I am supposed to be writing a code for a function that accepts a vector of pointers to a certain object, go through the list, and delete the invalid date from the list.我应该为 function 编写代码,该代码接受指向某个 object、go 的指针向量,然后从列表中删除无效日期。 So far, when testing, I keep getting an error that reads: "Exception thrown: read access violation" and I have been trying for the past few days to find the error, to no avail.到目前为止,在测试时,我不断收到一条错误消息:“抛出异常:读取访问冲突”,过去几天我一直在尝试查找错误,但无济于事。

Here's my code:这是我的代码:

#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;

class Reminder
{
private:
    int m_day;
    int m_month;
    string m_description;
    bool value;

public:

    Reminder(int day, int month, string description) : m_day(day), m_month(month), m_description(description)
    {

    }

    string toString()
    {
        stringstream sin;
        sin << m_month << "/" << m_day << ": " << m_description<<endl;
        return sin.str();
    }

    int getDay()
    {
        int day = m_day;
        return day;
    }

    int getMonth()
    {
        int month = m_month;
        return month;
    }



};

vector<Reminder*> removeInvalidDate(vector<Reminder*>& list)
{
    for (int count = 0; count < list.size(); count++)
    {
        if ((list[count]->getDay() < 1) || (list[count]->getDay() > 31))
            delete list[count];
        if ((list[count]->getMonth() < 1) || (list[count]->getMonth() > 12))
            delete list[count];
        else
            ;
    }

    return list;
}

int main()
{
    Reminder reminder1(7, 16, "Final Exam Due");
    Reminder reminder2(7, 4, "Independence Day Holiday");
    Reminder reminder3(1, 1, "Start of the New Year");
    Reminder reminder4(7, 30, "My Birthday");
    Reminder reminder5(1, -9, "Impossible Day1");
    Reminder reminder6(0, 0, "Impossible Day0");
    Reminder reminder7(0, 35, "Impossible day3");
    Reminder reminder8(13, 0, "Impossible");

    Reminder* pRe;
    pRe = new Reminder(reminder1);

    vector<Reminder*> list;

    list.push_back(pRe);

    pRe = new Reminder(reminder2);
    list.push_back(pRe);

    pRe = new Reminder(reminder3);
    list.push_back(pRe);

    pRe = new Reminder(reminder4);
    list.push_back(pRe);

    pRe = new Reminder(reminder5);
    list.push_back(pRe);

    pRe = new Reminder(reminder6);
    list.push_back(pRe);

    pRe = new Reminder(reminder7);
    list.push_back(pRe);

    pRe = new Reminder(reminder8);
    list.push_back(pRe);

    removeInvalidDate(list);

    return 0;
}

I think that the issue is either in setting up and passing the vector or in one of the class constructors.我认为问题在于设置和传递向量或 class 构造函数之一。

If both the day and the month are invalid, you're deleting list[count] twice如果日期和月份都无效,您将删除 list[count] 两次

if ((list[count]->getDay() < 1) || (list[count]->getDay() > 31))
    delete list[count];
if ((list[count]->getMonth() < 1) || (list[count]->getMonth() > 12))
    delete list[count];

I think that the issue is either in setting up and passing the vector or in one of the class constructors.我认为问题在于设置和传递向量或 class 构造函数之一。

Well, you can test both hypothesis.好吧,你可以检验这两个假设。 And you should actually do this!你真的应该这样做!

Firstly, you can test whether your constructors are causing a problem by simplifying your code to use vector<int> .首先,您可以通过简化代码以使用vector<int>来测试您的构造函数是否导致问题。 Just say the integer value is the day and leave out the month part for now.只需说 integer 值是日期,暂时忽略月份部分。

Secondly, you can set up the minimal vector with the simplest possible code - and just one element.其次,您可以使用最简单的代码设置最小向量 - 并且只需一个元素。 Or zero elements.或零元素。 And then add elements back until the problem recurs.然后重新添加元素,直到问题再次出现。

This kind of work, testing your understanding of the code, is perfectly normal and a good habit to start.这种工作,测试你对代码的理解,是完全正常的,也是一个好习惯。

Neither of those hypotheses will fix your current problem, but I'd encourage you to go back and do them anyway.这些假设都不能解决您当前的问题,但我鼓励您返回 go 并无论如何都要这样做。

This code这段代码

    if ((list[count]->getDay() < 1) || (list[count]->getDay() > 31))
        delete list[count];
    if ((list[count]->getMonth() < 1) || (list[count]->getMonth() > 12))
        delete list[count];
    else
        ;

has two main problems.有两个主要问题。 The first is that the layout suggests you intend首先是布局表明您打算

    if (X)
        A;
    elif (Y)
        B;
    else
        ;

but C++ doesn't have an elif .但是 C++没有elif If you don't want to remove the same element twice, it should be something like如果您不想两次删除相同的元素,则应该类似于

    if ((list[count]->getDay() < 1) || (list[count]->getDay() > 31))
    {
        delete list[count];
        continue;
    }
    if ((list[count]->getMonth() < 1) || (list[count]->getMonth() > 12))
    {
        delete list[count];
        continue;
    }

(or if () {... } else if () {... } or whatever). (或if () {... } else if () {... }或其他)。

The second and more serious problem is that delete list[count] is not how you remove elements from any container in C++.第二个也是更严重的问题是delete list[count]不是从 C++ 中的任何容器中删除元素的方式。 It's roughly how you'd do it in Python.这大致就是你在 Python 中的做法。 In C++ though, after delete list[count] , the element list[count] still exists but is a dangling pointer to the storage you just delete -d, and may never legally be dereferenced.但是在 C++ 中,在delete list[count]之后,元素list[count]仍然存在,但它是指向您刚刚delete -d 的存储的悬空指针,并且可能永远不会被合法地取消引用。 Since the very next thing you do is dereference it (for the month check), this causes your read access violation.由于您要做的下一件事是取消引用它(用于月份检查),这会导致您的读取访问冲突。

Any good book will tell you that std::vector::erase is how you remove elements from a vector, and that you should prefer std::remove_if to that, and that you should avoid storing (owning) raw pointers in containers in the first place.任何好书都会告诉您std::vector::erase是如何从向量中删除元素的方式,并且您应该更喜欢std::remove_if ,并且您应该避免在容器中存储(拥有)原始指针第一名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM