【问题标题】:Segmentation fault with allocation of pointer array?指针数组分配的分段错误?
【发布时间】:2016-05-20 07:01:01
【问题描述】:

过去几个小时我一直在试图弄清楚为什么会出现段错误。我的代码运行良好,因为我的 nameList 指针数组是用我输入的名称初始化的。但是,当我将 nameList 传递给我的函数以在 createStudentList 函数中为每个名称动态分配适量的空间时。如果您有任何想法,请告诉我一个解释,我不只是在寻找解决它的答案。谢谢你。 (这是一个赋值,所以需要遵循一些准则[例如使用 char 数组而不是字符串]。)

这是我的代码:

#include "main.h"
using namespace std;

const int MAXCHAR = 101;

struct Student
{
    char *name;
    double gpa;
};

Student ** createStudentList(char ** names, int size);

int main()
{
    int size = 0;
    char temp[MAXCHAR];
    char **nameList = nullptr;
    Student **studentList = nullptr;

    cout << "Enter amount of names: ";
    cin >> size;
    cout << endl;
    cin.clear();
    cin.ignore(10, '\n');
    nameList = new char *[size];

    for(auto i = 0; i < size; i++)
    {   
        cout << "Enter name: ";
        cin.get(temp, MAXCHAR, '\n');
        cout << endl;
        cin.ignore(10, '\n');
        nameList[i] = new char[strlen(temp) + 1]; 
        strcpy(nameList[i], temp);
    }   

    studentList = createStudentList(nameList, size);

    return 0;
}

Student ** createStudentList(char ** names, int size)
{
    Student **tempStudentList = nullptr;
    tempStudentList = new Student *[size];


    for(auto idx = 0; idx < size; idx++)
    {
        tempStudentList[idx]->name = new char[strlen(names[idx]) + 1];
        strcpy(tempStudentList[idx]->name, names[idx]);
        tempStudentList[idx]->gpa = 0;
    }
    return tempStudentList;
}

【问题讨论】:

  • 这不是现代 C++,使用标准库中的向量和字符串。你不应该依赖原始指针。
  • 请给我们看一个导致seg fault的案例
  • @tomekpe 我愿意,但我必须遵守作业的指导方针。我正在学习 C++ 课程,并且需要这样做。对不起
  • @tomekpe:100% 正确。但是,这是一项任务,OP 有特定的限制
  • @HumamHelfawi 不确定你的意思,但这就是 gdb 告诉我的。我输入了两个名字(Ryan 和 Ben),然后尝试将 nameList 传递给函数。程序收到信号 SIGSEGV,分段错误。 0x0000000000400e2c in createStudentList (names=0x614c20, size=2) at main.cpp:52 52 tempStudentList[idx]->name = new char[strlen(names[idx]) + 1];

标签: c++ function pointers struct segmentation-fault


【解决方案1】:

您没有在循环中分配 Student 实例。试试这个:

for(auto idx = 0; idx < size; idx++)
{
    tempStudentList[idx] = new Student;

    tempStudentList[idx]->name = new char[strlen(names[idx]) + 1];
    strcpy(tempStudentList[idx]->name, names[idx]);
    tempStudentList[idx]->gpa = 0;
}

另外,正如 cmets 中所指出的,这不是现代 C++。最好使用std::stringstd::vector。例如,将Student 更改为:

struct Student
{
    std::string name;
    double gpa;
};

createStudentList 中添加使用std::vector

std::vector<Student> createStudentList(const std::vector<string> &names)
{
    std::vector<Student> students;    

    for(auto idx = 0; idx < names.size(); idx++)
    {
        Student student;
        student.name = names[index];
        student.gpa = 0

        students.push_back(student);
    }

    return students;
}

这将使您不必分配原本需要删除的原始内存。

【讨论】:

  • 我会在推回之前保留。 student.reserve(names.size());
  • std::vector&lt;Student&gt; students(names.size()); 也可以。
  • 谢谢@Sean!我会试一试,不敢相信我没有注意到这一点。有时你盯着太久会错过明显的东西。感谢您提供有关矢量的提示。我现在在学校,对我的老师教我们不再现代的 C++ 感到非常失望。这个学期结束后,我真的需要学习更多。不过感谢您的帮助!此外,很高兴知道这些也有助于删除。此功能完成后,我的另一个目标是删除分配的内存。
【解决方案2】:

分段错误的原因:

for(auto idx = 0; idx < size; idx++)
{
    // tempStudentList[idx] is `Student *` and you don't allocate memory for it
    // this is UB
    tempStudentList[idx]->name = new char[strlen(names[idx]) + 1];
    strcpy(tempStudentList[idx]->name, names[idx]);
    tempStudentList[idx]->gpa = 0;
}

但是,tempStudentList 根本不需要是Student**Student* 就足够了。

Student * createStudentList(char ** names, int size)
{
    Student *tempStudentList = new Student[size];
    for(auto idx = 0; idx < size; idx++)
    {
        tempStudentList[idx].name = new char[strlen(names[idx]) + 1];
        strcpy(tempStudentList[idx].name, names[idx]);
        tempStudentList[idx].gpa = 0;
    }
    return tempStudentList;
}

BTW:你需要delete很多东西,nameListnameList的元素,studentListnameStudent,等等。这就是我们应该使用 STL 的原因。

【讨论】:

  • 感谢@songyuanyao的帮助。现在可以了!至于不必要的**,我没有任何其他选择,我为此作业提供的参数。至于删除,我将在我创建的下一个函数中处理所有这些,这是一个删除函数。再次感谢!
猜你喜欢
  • 2016-01-02
  • 2013-10-03
  • 1970-01-01
  • 1970-01-01
  • 2013-10-26
  • 2015-06-20
  • 1970-01-01
  • 2020-02-18
  • 1970-01-01
相关资源
最近更新 更多