Search code examples
c++arraysmallocrealloc

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


I wanted to see how c-arrays work. I made a few programs with malloc(), calloc() and realloc(). Every worked, except for this one:

#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;
}

I've been looking for a solution for an hour and I still don't understand why it crashes. I found that if I multiply the value in realloc(arr,(additional_students+2) * sizeof(*arr)); by 500, it somehow works. Why's that?


Solution

  • Beside wrong malloc implementation there are also other errors that can be fixed.

    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;
    }
    

    Making new student object just for assigning input to it and then transferring it to the array is unnecessary even if you had done custom "=" operator.
    Try something like this:

    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;
    }
    

    Since you already allocated room for two instances of student in the array, why create another one?
    The same exact thing has to be done in second loop.

    What about malloc you cannot use it when the struct contains C++ class objects that need to be constructed. As someone stated in the comments, malloc and realloc only allocate the memory, and they don't construct the struct itself (if it has any constructor) or the member of the struct (I'm talking about the string members).
    If you want to keep current solution with malloc and realloc try to use char name[255]; and char surname[255]; instead of your existing string members. And also change the loops as I stated before, because it can lead to unpredictable behavior.

    EDIT: Or just use std::vector instead, which constructs everything properly.

    Working code, with kept malloc and realloc

    #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;
    }