【问题标题】:Stack Overflow error when instantiating a new Class实例化新类时出现堆栈溢出错误
【发布时间】:2014-11-08 23:44:33
【问题描述】:

我有一个“类”类,它有一个字符串名称和一个“学生”对象数组。 “学生”类有一个名字和“成绩”。 “成绩”类是一个双精度数组。

在主类中,我创建了一个 Grades 对象和一个 Student 对象。我用它测试了一些功能,一切都很好:

int main(){

    cout << fixed << setprecision(2);

    Grades test = Grades ("5 - 90.0 85.0 95.5 77.5 88.0");
    cout << test.toString() << endl;
    cout << "\nSum  = " << test.getSum() << endl;
    cout << "Num grades  = " << test.getNumGrades() << endl;
    cout << "Low grade  = " << test.getLowGrade() << endl;
    cout << "High grade  = " << test.getHighGrade() << endl;

    Student stu = Student("Billy Bob", "5 - 90 85 95.5 77.5 88");
    cout << stu.toString() << endl;
    cout << "\nSum  = " << stu.getSum() << endl;
    cout << "Average  = " << stu.getAverage() << endl;
    cout << "Average after dropping low grade  = " << stu.getAverageMinusLow() << endl;
    cout << "Low grade  = " << stu.getLowGrade() << endl;
    cout << "High grade  = " << stu.getHighGrade() << endl;

}

但是当我添加该行时:

Class testClass = Class("Comp Sci 1", 3);

然后运行程序,它有一个堆栈溢出错误。 “Gradebook.exe 中 0x0033EAB7 处的第一次机会异常:0xC00000FD:堆栈溢出(参数:0x00000000、0x003D2000)。”

如果有这个异常的处理程序,程序可以安全地继续。 是因为对象太多,每个对象都是另一个对象的成员吗?有没有办法“删除”我在此行之前创建的“测试”和“stu”对象?

这是我的“类”构造函数供参考:

class Class{
    private:
        string name;
        Student studentList[100];
        int numStudents;

    public: Class(string className, int numStudents1);
            Class();
}

Class:: Class(string className, int numStudents1){
    name = className;
    numStudents = numStudents1;

}
Class:: Class(){
    name = "";
    numStudents = 0;
}

出现这个错误是因为 Class 对象中的“studentList”学生数组没有在构造函数中实例化吗?

【问题讨论】:

  • 为什么不Class testClass("Comp Sci 1", 3);?除此之外,您必须显示更多代码才能找出问题所在。
  • 您似乎混淆了堆栈和堆实例化。现在,由于您分配它们的方式,您正在导致不必要的复制操作。
  • 另外,当您确定学生人数为 100 时,为什么还要通过学生人数?改为使用向量,并且只拥有您需要的尽可能多的学生。这样学生就不会在堆上被放入堆栈,这可能是你得到溢出的原因。
  • 您所做的创建了一个类,然后将其复制到 testClass,这是不必要的。但是您的实施策略还有其他问题。
  • 谢谢@ddriver。这行得通。我肯定会在 C++ 中查看更多的堆栈分配和堆分配。我不能使用矢量,因为我的老师不允许。否则,我肯定会使用它。

标签: c++ class stack-overflow


【解决方案1】:

在函数中声明的每个变量都位于堆栈上,在函数外部声明的变量是静态变量并使用data segment

Class testClass("Comp Sci 1", 3);

int main(){

这在某些方面也很糟糕,但不如导致堆栈溢出那么严重。

【讨论】:

  • ...?堆和静态数据段不等价。
  • @milleniumbug 很多事情都在发生。似乎是某些特定实现引发的混乱。
  • 堆是数据段的一部分(至少维基百科同意这一点......但你不应该相信维基上的所有内容)。
【解决方案2】:

这种设计显然是错误的。

Student 中应该有一个矢量或类似的容器来保存所有成绩,Class 中应该有一个类似的容器来保存所有学生。你说你的老师不允许你使用vector,这看你的水平并没有多大意义,但也许他希望你创建自己的容器类?同样,您似乎还没有完全到达那里,所以这是一种悖论。

您的问题是您在一个班级中为 100 名学生分配了足够的存储空间,而这 100 名学生可能有很多成绩,因此班级最终可能会变得庞大,太大而无法放入堆栈,这就是为什么溢出。这样,班级加上学生加上成绩就形成了一大块“平坦”的记忆。当您使用这种形式的实例化Class testClass = Class(...) 而不进行编译器优化时,它创建的不是一个而是两个对象,只是将后者分配给前者。修复类构造函数(你也应该修复另一个)可能会修复溢出问题,但它不能修复你的设计问题。

Class 这样的大结构在内存中不是平坦的会更简单,也是推荐的好习惯。让它平坦实际上更复杂,但可能具有其他优势(例如性能或内存效率)并且仍然可以安全地用于动态分配,但在您的情况下,您对一流的效率不感兴趣,但需要理解并因此拥有好的设计。

此外,正如 cmets 中所述,使用成绩创建学生是错误的,尤其是通过字符串文字的成绩。如果这是一个你必须在实践中使用的真正程序,如果成绩还没有到来,你将如何在年初创建具有所有成绩的新学生?您的 Student 类构造函数应该只传递学生的名称,而应该有一个 addGrade() 成员函数。

那个 Class 对象预分配了一个长度为 100 的静态数组呢?如果你只有 3 个学生,那么将浪费 97 个学生的内存。如果你需要超过 100 名学生怎么办?你的程序崩溃了。这就是为什么你应该使用一个容器并且只有你需要的学生数量。而且我只能假设学生班级内部正在发生同样可怕的事情。这些类型的“技术”通常用于旧的 C 代码中,这可能是您的老师所困扰的问题,但肯定不推荐用于现代 C++ 的教学。

【讨论】:

    猜你喜欢
    • 2016-03-14
    • 2019-05-18
    • 1970-01-01
    • 2016-11-14
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多