【问题标题】:Exception thrown at 0x0F4D514F (vcruntime140d.dll) in Project70.exe: 0xC0000005: Access violation writing location 0xDDDDDDDD在 Project70.exe 中的 0x0F4D514F (vcruntime140d.dll) 处引发异常:0xC0000005:访问冲突写入位置 0xDDDDDDDD
【发布时间】:2020-02-13 04:44:21
【问题描述】:

我正在尝试使用地址更改在堆中创建的类成员的值,并在下面显示错误。

class class2 {
private:
    string String = "x";
public:
    string function() {
        return String;
    }
};

class class1 {
public:
    string String;
    class2* i;
        void  address(class2* x) {
        x = new class2();
        i = x;
    }

        void function(string x) {
            String = x;
    }
};



int main() {
    int len;
    cin>>len;
    class1 **Class1 = new class1*[len];

    for(int i = 0; i < len; i++) {
        Class1[i] = new class1[i];
    }

    Class1[0]->address(Class1[0]->i);
    Class1[0]->function(Class1[0]->i->function());
    cout<<Class1[0]->String;

}

在 Project70.exe 中的 0x0F4D514F (vcruntime140d.dll) 处引发异常: 0xC0000005:访问冲突写入位置0xDDDDDDDD。

【问题讨论】:

  • 请显示minimal reproducible example。你可以edit你的问题。但是class1 **Class1 中的两颗星不好看,记住你用的是c++,不是C。
  • new class1[i] 应该做什么?
  • 你的意见是什么?
  • 当 i 为 0 时,Class1[0] = new class1[0]; 正在分配零个 class1 对象。取消引用 0 个对象的数组 Class1[0]-&gt;address 正在做 UB。在那之后,所有的赌注都被取消了。
  • @Eljay UB:未定义的行为?善待新程序员。

标签: c++ class new-operator undefined-behavior memory-mapped-files


【解决方案1】:

新操作员的这个调用

Class1[i] = new class1[i];

无效。你的意思是

Class1[i] = new class1; 

注意这个成员函数

void  address(class2* x) {
        x = new class2();
        i = x;
    }

没有太大意义,因为没有使用传递给函数的参数。

【讨论】:

    【解决方案2】:

    好的,让我们一步一步来说明问题所在。很明显你正在学习 C++,所以我会尝试写信给那些听众。

        int len;
        cin>>len;
    

    1) 从标准中读取一个长度。还没有严重的问题。您可以检查以确保它不是负数或零,但我们现在就让它滑动。我们假设“len = 3”,然后从这里继续。

        class1 **Class1 = new class1*[len];
    

    2) 你创建了一个指向 class1 的指针,称为 Class1。我不能说我喜欢你的命名方案,但让工作也通过它,并将 Class1 设置为指向 class1 的指针数组。到目前为止,一切都很好。如果len 为零或负数,您可以想象您可能遇到的问题。请注意,这些指针的所有内存都没有被初始化,只是留出来保存你以后放入的东西。

        for(int i = 0; i < len; i++) {
            Class1[i] = new class1[i];
        }
    

    3) 这将创建 class1 的一些新实例,并将 Class1[I] 指向它们。使用len = 3,这将创建一个奇怪的分配网格。第一个数组的长度为零,第二个长度为 1,第三个长度为 2。零长度数组不好。

    所以当我们踩到这个零长度数组时,它会像地雷一样爆炸,让我们去散散步吧!

    Class1[0]->address(Class1[0]->i);
    

    首先,这是非常具有误导性的。最好写成Class1[0][0].address(Class1[0][0].i);其次,将“i”传递给一个函数,其唯一目的是写入一个恰好是您刚刚传入的参数的成员变量是没有意义的。写入成员变量即可。

    第三个:繁荣。我们刚刚踩到了零长度阵列地雷。但一切都没有丢失。

    您可以通过相对较少的更改来挽救这一点。

    • Class1[i] = new Class1[len]; 将为您提供分配网格 (3, 3, 3) 而不是三角形 (0, 1, 2)。
    • 对于每次调用new,您都需要调用delete,最好是在该类的析构函数中。析构函数很棒。你在address 中调用new(去掉它的参数,你不需要它),所以某处需要调用delete。此外,您应该在构造函数中将 i 设置为 nullptr,这样您就不会意外尝试删除无效的内容。
    • 每次拨打new[],您都需要拨打delete[]。您遍历了一个调用 new[] 的数组,因此您需要遍历调用 delete[] 的数组来清理它。
    • 变量名称。我猜英语不是你的第一语言,而且你也在学习 C++,所以我理解。但是,您的函数和变量名称充其量是毫无意义的(class1class2ix),最坏的情况是误导(address 不占用任何地址,它会创建一些东西)。即使没有太多事情要做,您至少可以使用“InnerClass”、“OuterClass”、“message”、“createInner”、“innerPtr”之类的名称......而且它们几乎不会那么难以弄清楚。

    &lt;RANT MODE&gt; 我们是什么,数学家?!我们拥有描述事物所需的所有空间,因此要具有描述性。数学家过去常常被限制在黑板上,必须手写所有内容,因此使用(过度)简洁(外人无法理解)符号的压力是可以理解的……但是现在呢?他们连这个借口都没有。我也在看着你们 物理学家!是的,你,穿着白大褂! &lt;/RANT MODE&gt;

    并学会触摸打字。程序员最终会输入很多内容,并且在屏幕和键盘之间来回查看会影响您的打字速度。

    【讨论】:

    • 你最好完全放弃原生数组并使用std::vector&lt;class1&gt;,但我猜你还没有了解模板。
    • 我们已经被介绍过,但在这个作业中是不允许的。
    猜你喜欢
    • 2018-06-26
    • 2020-08-09
    • 2021-07-03
    • 2016-11-12
    • 1970-01-01
    • 2021-03-06
    • 2019-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多