为什么将新结构放入重新分配的 c 数组会导致程序崩溃?

Why putting new structures into reallocated c-array crashes program?

我想看看 c 数组是如何工作的。我用 malloc(), calloc() and realloc(). 制作了几个程序,每个程序都有效,除了这个:

#include <iostream>

using namespace std;

struct student
{
    string name;
    string surname;
    int age;
};

int main(){
  student* arr = (student*)malloc(2*sizeof(student));
  if(arr!=NULL){
    for(int i = 0;i<2;i++){
        student st;
        cout<<"Enter name of "<<i+1<<". student: ";
        cin>>st.name;
        cout<<endl<<"Enter surname of "<<i+1<<". student: ";
        cin>>st.surname;
        cout<<endl<<"Enter age of "<<i+1<<". student: ";
        cin>>st.age;
        cout<<endl;
        arr[i] = st;
    }
     for(int i = 0;i<2;i++){
            cout<<"Name of "<<i+1<<". student: "<<arr[i].name<<endl<<endl;
            cout<<"Surname of "<<i+1<<". student: "<<arr[i].surname<<endl<<endl;
            cout<<"Age of "<<i+1<<". student: "<<arr[i].age<<endl<<endl;

     }
     cout<<endl<<"How many students would you like to add? ";
     int additional_students;
     cin>>additional_students;
     arr = (student*) realloc(arr,(additional_students+2) * sizeof(*arr));
     if(arr !=NULL){
         for(int i = 2;i<2+additional_students;i++){
        student st;
        cout<<"Enter name of "<<i+1<<". student: ";
        cin>>st.name;
        cout<<endl<<"Enter surname of "<<i+1<<". student: ";
        cin>>st.surname;
        cout<<endl<<"Enter age of "<<i+1<<". student: ";
        cin>>st.age;
        cout<<endl;
        //this line crashes the program
        arr[i] = st;
    }
     for(int i = 0;i<2+additional_students;i++){
            cout<<"Name of "<<i+1<<". student: "<<arr[i].name<<endl;
            cout<<"Surname of "<<i+1<<". student: "<<arr[i].surname<<endl;
            cout<<"Age of "<<i+1<<". student: "<<arr[i].age<<endl;
     }
     }
      }
  free(arr);
  return 0;
}

我已经找了一个小时的解决方案,但我仍然不明白它为什么会崩溃。我发现如果我将 realloc(arr,(additional_students+2) * sizeof(*arr)); 中的值乘以 500,它会以某种方式起作用。这是为什么?

除了错误的 malloc 实现之外,还有其他可以修复的错误。

for(int i = 0;i<2;i++){
    student st;
    cout<<"Enter name of "<<i+1<<". student: ";
    cin>>st.name;
    cout<<endl<<"Enter surname of "<<i+1<<". student: ";
    cin>>st.surname;
    cout<<endl<<"Enter age of "<<i+1<<". student: ";
    cin>>st.age;
    cout<<endl;
    arr[i] = st;
}

创建新的学生对象只是为了为其分配输入然后将其传输到数组是不必要的,即使您已经完成了自定义“=”运算符。
尝试这样的事情:

for(int i = 0; i < 2; i++){
    cout << "Enter name of " << i + 1 << ". student: ";
    cin >> arr[i].name;
    cout << endl << "Enter surname of " << i + 1 << ". student: ";
    cin >> arr[i].surname;
    cout << endl << "Enter age of " << i + 1 << ". student: ";
    cin >> arr[i].age;
    cout << endl;
}

既然你已经为数组中的两个 student 实例分配了空间,为什么还要创建另一个?
在第二个循环中必须完成同样的事情。

malloc 当结构包含需要构造的 C++ class 对象时不能使用它。正如评论中有人所说,mallocreallocallocate 内存,而他们没有构造结构本身(如果它有任何构造函数)或结构的成员(我说的是 string 成员)。
如果您想使用 mallocrealloc 保持当前解决方案,请尝试使用 char name[255];char surname[255]; 而不是您现有的字符串成员。还要像我之前所说的那样更改循环,因为它会导致不可预测的行为。

编辑: 或者只使用 std::vector 来代替,它可以正确地构建所有内容。

工作代码,保留 mallocrealloc

#include <iostream>

using namespace std;

struct student
{
    char name[255];
    char surname[255];
    int age;
};

int main(){
  student* arr = (student*)malloc(2*sizeof(student));
  if(arr!=NULL){
    for(int i = 0;i<2;i++){
        cout<<"Enter name of "<<i+1<<". student: ";
        cin>>arr[i].name;
        cout<<endl<<"Enter surname of "<<i+1<<". student: ";
        cin>>arr[i].surname;
        cout<<endl<<"Enter age of "<<i+1<<". student: ";
        cin>>arr[i].age;
        cout<<endl;
    }
     for(int i = 0;i<2;i++){
            cout<<"Name of "<<i+1<<". student: "<<arr[i].name<<endl<<endl;
            cout<<"Surname of "<<i+1<<". student: "<<arr[i].surname<<endl<<endl;
            cout<<"Age of "<<i+1<<". student: "<<arr[i].age<<endl<<endl;

     }
     cout<<endl<<"How many students would you like to add? ";
     int additional_students;
     cin>>additional_students;
     arr = (student*) realloc(arr,(additional_students+2) * sizeof(*arr));
     if(arr !=NULL){
         for(int i = 2;i<2+additional_students;i++){
        cout<<"Enter name of "<<i+1<<". student: ";
        cin>>arr[i].name;
        cout<<endl<<"Enter surname of "<<i+1<<". student: ";
        cin>>arr[i].surname;
        cout<<endl<<"Enter age of "<<i+1<<". student: ";
        cin>>arr[i].age;
        cout<<endl;
    }
     for(int i = 0;i<2+additional_students;i++){
            cout<<"Name of "<<i+1<<". student: "<<arr[i].name<<endl;
            cout<<"Surname of "<<i+1<<". student: "<<arr[i].surname<<endl;
            cout<<"Age of "<<i+1<<". student: "<<arr[i].age<<endl;
     }
     }
      }
  free(arr);
  return 0;
}