【问题标题】:Access Violation trying to read vector filled with objects访问冲突试图读取填充有对象的向量
【发布时间】:2015-08-19 10:18:15
【问题描述】:

编辑:我做了一些更改并更新了这篇文章中的代码 Kyle 和 Dieter 的 cmets,所以我修复了 Clone() 函数并 添加了一个赋值运算符来满足三规则。虽然这 修复肯定是急需的,同样的错误盛行。也许我的 赋值运算符错了?

我正在使用我在网上找到的库 jsonplus 来完成一个更大的项目。 我需要将 CJsonArray 类的对象保存在向量中。 CJsonArray 没有 Copy-Constructor 但有一个指针属性,所以我尝试自己制作一个(第一次制作复制构造函数,我是 c++ 新手)。

这里是CJsonArray的相关部分:

cjsonarray.h

    class CJsonArray : public CJsonValue
    {
    private:
      std::vector <CJsonValue*> members;
    public:
        LIB_PRE CJsonArray();
        LIB_PRE CJsonArray(const CJsonArray * value);
        LIB_PRE CJsonArray(const CJsonArray &); //the added copy constructor
        LIB_PRE CJsonArray& operator=(const CJsonArray&);
        LIB_PRE ~CJsonArray();

cjsonarray.cpp

 CJsonArray::CJsonArray(const CJsonArray& ori) : members(ori.members.size()) {
        for (std::size_t i = 0; i < ori.members.size()-1; ++i)
            members[i] =ori.members[i]->Clone();
    }
CJsonArray& CJsonArray::operator=(const CJsonArray& ori){
    for (std::size_t i = 0; i < ori.members.size() - 1; ++i){
        this->members[i] = ori.members[i]->Clone();
    }   
    return *this;
}

此外,我必须在 CJsonValue 中实现一个 clone() 函数,它是一个抽象类以及从它派生的类。以下是相关代码sn-ps:

cjsonvalue.h

enum CJsonValueType
{
  JV_STRING,
  JV_NUMBER,
  JV_OBJECT,
  JV_ARRAY,
  JV_NULL,
  JV_BOOL
};

class CJsonValue
{
private:
  CJsonValueType type;
public:
  LIB_PRE CJsonValue();
  LIB_PRE virtual ~CJsonValue();
  LIB_PRE CJsonValue(CJsonValueType type);
  LIB_PRE virtual CJsonValue * Clone(); //the added Clone-Function
  LIB_PRE virtual jstring ToString() const = 0;
  LIB_PRE CJsonValueType GetType() const;
  LIB_PRE virtual void Clear(){};
};

cjsonvalue.cpp

    CJsonValue * CJsonValue::Clone(){
    return NULL;
}

派生类示例,cjsonvaluenumber.h

    class CJsonValueNumber : public CJsonValue
{
private:
  int value;
public:
  LIB_PRE CJsonValueNumber(int value);
  LIB_PRE CJsonValueNumber(const CJsonValueNumber * value);
  LIB_PRE CJsonValue * Clone();
  LIB_PRE jstring ToString() const;
  LIB_PRE void GetValue(int & number) const;
};

cjsonvaluenumber.cpp

CJsonValue * CJsonValueNumber::Clone(){
    return new CJsonValueNumber(*this);
}

产生错误的main.cpp:

 CJsonArray array1;
 CJsonArray array2;
 CJsonArray array3;
 CJsonArray array4;
 CJsonArray array5;

 array1.AddMember("test1");
 array2.AddMember("test1");
 array3.AddMember("test1");
 array4.AddMember("test1");
 array5.AddMember("test1");

 arrays.push_back(array1);
 arrays.push_back(array2);
 arrays.push_back(array3);
 arrays.push_back(array4);
 arrays.push_back(array5);

 std::string str = arrays[0].ToString();

错误:

Message.exe 中 0x026574BD 处未处理的异常:0xC0000005:访问 违规读取位置0x00000000。

调试信息: 在第一个 push_back 上,第一个条目的成员已经损坏。 在我实现 Copy-Constructor 之前,程序在第二次或第三次推回时已经崩溃,我猜是因为 vectore 必须重新分配他的条目并且找不到它们?我很伤心,我第一次不得不处理这个问题。

所以我的问题是:我做错了复制构造函数吗?还是我完全走错了路,与它无关?

我查看了许多其他处理类似问题的 Stackoverflow 问题,并尝试遵循那里的建议,但我想我在此过程中做错了。

如果我需要提供更多信息,请告诉我。

提前感谢您的帮助!

【问题讨论】:

  • 可能:三 (5) 规则 - 缺少赋值运算符
  • 哇,感谢您的快速答复!我会仔细看看的。同时,你能告诉我是否在 cjsonvalue.cpp 中实现了 clone() 函数吗?我很不确定是否只在那里返回一个 NULL。
  • 你知道Clone 不是虚拟的,对吧?
  • 我添加了一个赋值运算符(我希望我做得对)但问题仍然存在。我在 OP 中编辑了代码以反映我的更改。
  • 出于好奇,CJsonValueNumber(const CJsonValueNumber * value); 应该服务于什么目的? return new CJsonValueNumber(*this); 肯定不会调用它,并且您的 JsonArray 将在您添加的赋值运算符上调用未定义的行为,除非右值 完全this-&gt;members 的大小匹配。既然你遇到了这么多麻烦,为什么不干脆把它结束并发布一个真实 MCVE 以便花更少的时间去想没有显示什么,以及更多时间了解

标签: c++ vector clone copy-constructor


【解决方案1】:

CJsonValue::Clone() 方法需要是虚拟的。如果CJsonArray 对象存储CJsonValue 对象的集合(与CJsonValueNumber 或其他对象相反),则编译器无法知道CJsonValueNumber 想要覆盖Clone() 方法(如果它不是虚拟的)。

这将导致总是调用CJsonValue::Clone() 而不是CJsonValueNumber::Clone()。此时,您的数组中有 NULL 引用,这可能会导致您在 0x00000000 处的访问冲突(NULL 定义为 00x00000000)。

由于CJsonValue 无论如何都是一个抽象类(CJsonValue::ToString() 方法是 virtual void),我也会将 CJsonValue::Clone() 设为 virtual void。这将保证 Clone 方法必须通过继承类来实现。

总而言之,将CJsonValue::Clone() 的声明更改为:

LIB_PRE virtual CJsonValue * Clone() = 0;

【讨论】:

  • 谢谢,我改了,我相信这也是个问题,但是执行主函数时我仍然遇到同样的错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-25
  • 2013-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多