【问题标题】:C++: How do I correct the read access violation that my code doesC++:如何更正我的代码的读取访问冲突
【发布时间】:2020-11-06 16:05:57
【问题描述】:

我是 C++ 的初学者,我一直在尝试自己解决一些问题。我应该为一个函数编写代码,该函数接受指向某个对象的指针向量,遍历列表,然后从列表中删除无效日期。 到目前为止,在测试时,我不断收到一条错误消息:“抛出异常:读取访问冲突”,过去几天我一直在尝试查找错误,但无济于事。

这是我的代码:

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

我认为问题在于设置和传递向量或类构造函数之一。

【问题讨论】:

  • vector&lt;Reminder*&gt; 有点傻,因为这里不需要任何堆分配,只需使用vector&lt;Reminder&gt;delete list[count]; 释放分配但不从向量中删除指针。 removeInvalidDate() 不必要地返回向量的副本。
  • 您的程序中无需使用任何指针或手动分配内存。
  • 我是 C++ 的初学者,一直在尝试自己解决一些问题 -- 此外,C++ 是一种非常复杂的语言,如果不是最复杂的语言之一学习复杂的高级语言。使用经过同行评审的 C++ 书籍是学习 C++ 的理想方式。
  • 除非您在该主题上有很好的指导,否则您应该考虑将newdelete 和其他形式的手动内存管理作为高级主题,并在您具备以下基础知识时保存它们C++ 掌握得很好。

标签: c++ class pointers vector


【解决方案1】:

如果日期和月份都无效,您将删除 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];

【讨论】:

    【解决方案2】:

    我认为问题在于设置和传递向量或类构造函数之一。

    嗯,你可以检验这两个假设。你真的应该这样做!

    首先,您可以通过简化代码以使用vector&lt;int&gt; 来测试您的构造函数是否导致问题。只需说整数值是日期,暂时省略月份部分。

    其次,您可以使用最简单的代码设置 minimal 向量 - 并且只需一个元素。或零元素。然后重新添加元素,直到问题再次出现。

    这种测试你对代码的理解的工作是完全正常的,也是一个很好的开始。

    这些假设都不能解决您当前的问题,但我鼓励您无论如何都回去做。

    这段代码

        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
            ;
    

    有两个主要问题。首先是布局建议您打算

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

    但 C++ 没有elif。如果你不想删除同一个元素两次,它应该是这样的

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

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

    第二个也是更严重的问题是delete list[count] 不是在 C++ 中如何从任何容器中删除元素。这大致就是你在 Python 中的做法。但是在 C++ 中,在 delete list[count] 之后,元素 list[count] 仍然存在,但它是指向存储空间的悬空指针 delete-d,并且可能永远不会被合法地取消引用。由于您接下来要做的是取消引用它(用于月份检查),这会导致您的读取访问冲突。

    任何好书都会告诉您std::vector::erase 是您从向量中删除元素的方法,您应该更喜欢std::remove_if,并且您应该首先避免在容器中存储(拥有)原始指针.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-18
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-17
      相关资源
      最近更新 更多