【问题标题】:Segmentation fault with dynamically allocated arrays as members of structure in c++?动态分配的数组作为c ++中结构的成员的分段错误?
【发布时间】:2017-12-10 19:49:27
【问题描述】:

我正在编写一个程序,它使用一个结构数组来存储一定数量学生的姓名、身份证号和一组考试成绩。结构数组和测试分数成员数组都需要动态分配。我已经开始使用允许用户输入每个学生的考试成绩的功能,但是我在最后一个函数(getScores 函数)中遇到了 cin 问题。使用 Linux 时出现分段错误,因此我假设它与作为结构成员的动态分配的测试数组有关,我只是看不到它。我想知道如何调试它并解释为什么会发生这种情况,以便将来避免它。

//Preprocessor Directives
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;

//Structure declaration
struct Students
{
    string name; //Student name
    int idNum; //Student ID number
    double *tests; //Pointer to an array of test scores
};

//Function prototypes
Students *getStudents(int &);
double *getTests(int &);
void getInfo(string &, int &, int);
void getScores(double &, string, int);

//Main program section
int main ()
{
    int numStudents = 0;
    int numTests = 0;
    Students *studentFiles = NULL;

    //Call the getStudents function
    studentFiles = getStudents(numStudents);

    //Call the getTests function
    studentFiles->tests = getTests(numTests);

    for(int i = 0; i < numStudents; i++)
    {
        //Call the getInfo function
        getInfo(studentFiles[i].name, studentFiles[i].idNum, i+1);
    }

    for(int i = 0; i < numStudents; i++)
    {
        for(int j = 0; j < numTests; j++)
        {
            getScores(studentFiles[i].tests[j], studentFiles[i].name, j);
        }
    }
    delete [] studentFiles;
    delete [] studentFiels->tests;
    return 0;
}

Students *getStudents(int &numStudents)
{
    Students *studentFiles = NULL;

    //Prompt the user for the number of students
    cout<<"Enter the number of students: ";
    cin>>numStudents;
    //Dynamically allocate an array of structs, one for each student
    studentFiles = new Students[numStudents];

    return studentFiles;
}

double *getTests(int &numTests)
{
    double *tests = NULL;

    //Prompt the user for the number of tests
    cout<<"Enter the number of tests: ";
    cin>>numTests;
    cin.ignore();
    //Dynamicall allocate an array of integers, one for each test 
    tests = new double[numTests];

    return tests;
}

void getInfo(string &name, int &idNum, int index)
{
    //Prompt for each student's name and id number
    cout<<"Enter the name of student #"<<index<<": ";
    getline(cin, name);
    cout<<"Enter the id number of student #"<<index<<": ";
    cin>>idNum;
    cin.ignore();
}

void getScores(double &test, string name, int numTest)
{
    cout<<name<<endl;
    cout<<numTest<<endl;
    //Prompt for each test score for each student
    cout<<"Enter "<<name<<"'s score for test #"<<numTest+1<<": ";
    cin>>test;
}

【问题讨论】:

  • 你调试代码了吗?你做的时候看到了什么?它在哪里崩溃,内存值是多少,...
  • 只要有一个以上的学生,它就会崩溃,就在 getScores 函数中的最后一个 cin 之后。似乎它没有读取最后一个值,因为也许没有地方可以放置它或其他东西,但我不明白为什么。如果我输入 2 个学生 2 个测试,它将通过第一个学生的前两个测试分数。当它获得第二个学生的输入测试分数时,您可以输入分数,按 Enter,然后它会崩溃。这就是 Linux 给我的分段错误。
  • studentFiles-&gt;tests = getTests(numTests); - studentFiles 是指向代码中的数组的指针,但在这里你取消引用它就像它是指向单个元素的指针一样 -> 只有你的第一个 Student 对象有一个有效的tests 指针,其他的都没有(所以你得到未定义的行为
  • @UnholySheep 好的,这确实有道理,因为如果只有一个学生,它就可以工作。如何让每个Student 对象都有一个有效的测试指针?
  • 您需要遍历所有 Students 对象并为每个 tests 分配一个有效指针(例如,使用您的 getTests 函数)

标签: c++ arrays pointers segmentation-fault structure


【解决方案1】:

一个错误是您访问了已删除对象studentFiles 的成员。反转行来解决这个问题:

delete [] studentFiles->tests;    
delete [] studentFiles;

理想情况下,使用std::vector&lt;&gt; 而不是手动动态分配和释放内存。

另请注意,代码仅初始化数组第一个成员的Student::tests,其余Student 对象的此成员未初始化。表达式studentFiles[i].tests[j] 的结果是未定义的,可能会导致崩溃。

您需要初始化每个StudentStudent::tests 成员。完成后,释放每个Student 中的Student::tests

【讨论】:

  • +1 表示std::vector 建议。使用正确的 RAII 还有助于确保对象按照声明的相反顺序正确销毁,这就是这里的问题
  • 这似乎并没有解决问题,我们刚刚介绍了动态内存分配,所以我不知道如何使用您提供的其他解决方案。
  • @mobandy644 添加了关于Student::tests的注释。
  • @MaximEgorushkin 谢谢你,现在说得通了,有没有办法创建每个“学生”对象的测试成员,以便程序正常工作?
  • @mobandy644 你的程序错过了初始化每个学生和每个测试的循环。
猜你喜欢
  • 2017-06-11
  • 1970-01-01
  • 2021-08-11
  • 1970-01-01
  • 2014-08-22
  • 2021-06-24
  • 1970-01-01
  • 2021-03-21
  • 2020-05-26
相关资源
最近更新 更多