0xC0000005: Access violation writing location 0xCDCDCDCD Dynamic Allocation Error

-1

Getting 0xC0000005: Access violation writing location 0xCDCDCDCD with the code below. I know I must have not allocated the pointer properly, but I'm not sure where.

I'm trying to have **scoreSet refer to sets of *scores and *scores is to be entered in manually. The names pointer to array is working fine and seems to be allocated properly. The problem is when I try to mimic the same for scoreSet, with the difference being scoreSet is a pointer to an array of pointers scores. I feel like the way I'm trying to dynamically allocate the arrays that this pointer is pointing to is completely wrong.

Basically trying to get something like this to be possible after user input: scoreSet0 = {22,33,44} scoreSet1 = {35, 45, 65, 75} scoreSet3 = {10}

#include <iostream>
#include <string>
using namespace std;

int inputData(string*& names, double**& scores);

int main() {
    string *names = nullptr;
    double *scores = nullptr;
    double **scoreSet = &scores;
    int size = 0;
    size = inputData(names, scoreSet);
    for (int i = 0; i < size; i++) {
        cout << *(names+i) << endl;
    }
}

int inputData(string*& names, double**& scoreSet) {
    int numStudents = 0;
    cout << "How many students do you have in the system? ";
    cin >> numStudents;
    while (numStudents <= 0) {
        cout << "Invalid number of students. Please enter number of students: ";
        cin >> numStudents;
    }
    names = new string[numStudents];
    cin.ignore(10000, '\n');
    for (int i = 0; i < numStudents; i++) {
        int numTests = 0;
        cout << "Enter the student's name: ";
        getline(cin,names[i]);
        cout << "Enter how many tests " << *(names + i) << " took: ";
        cin >> numTests;
        *(scoreSet + i)= new double[numTests];                   //Pretty sure this is wrong.
        cin.ignore(10000, '\n');
        for (int j = 0; j < numTests; j++) {                //This loop is causing the error.
            cout << "Enter grade #" << j + 1 << ": ";
            cin >> *(scoreSet+i)[j];
        }
    }
    return numStudents;
}
c++
arrays
pointers
dynamic-memory-allocation
asked on Stack Overflow Jan 27, 2020 by Austin Chow

2 Answers

0

Per PaulMcKenzie suggestion, this is how it would roll. It may be a bit much for you to use templates, but if you can... Otherwise create the name and score containers separately. But then you have duplicate code to maintain.

The idea is to keep all your stuff in some kind of order. Note that now the memory management is taken care of in the container.

I dropped handling std::cin and the scores, but it should be much easier for you to code that stuff back without a lot of fluff in the way. At that, develop without std::cin, it is a waste of time. You should write so you can just edit and run.

Also, get out of the habit of using namespace std; It will pay off in the long run.

#define DEV
template<typename T>
struct container {
    size_t size;
    T* ar;
    container(size_t size) :size(size) {
        ar = new T[size];
    }
    ~container() { delete[]ar; }
    T& operator [](size_t pos) { return ar[pos]; }
};
using names_c = container<std::string>;
using scores_c = container<double>;

size_t inputData(names_c& names, scores_c& scores);

int main() {
    container<std::string> names(2);
    container<double> scoreSet(2);

    auto size = inputData(names, scoreSet);
    for (int i = 0; i < size; i++) {
        std::cout << names[i] << endl;
    }
}

size_t inputData(names_c& names, scores_c& scores) {
#ifdef DEV
    size_t numStudents = 2;
    names[0] = "tom";
    names[1] = "mary";
#else
    //do your std::cin stuff
#endif
    return names.size;
}

I wasn't going to go there, but. You can extend the concept so that you have containers in containers. Much easier to know what scores go with what student.

struct student_type {
    using scores_c = container<double>;
    std::string name;
    scores_c scores;
};
using student_c = container<student_type>;
answered on Stack Overflow Jan 27, 2020 by lakeweb • edited Jan 27, 2020 by lakeweb
0

I've taken your code, and modified it to work. I've removed your comments, and placed comments in on the lines that I changed.

#include <iostream>
#include <string>
using namespace std;

int inputData( string *&names, double **&scores );

int main() {
    string *names = nullptr;
    double **scores = nullptr; // Changed to double ** so it's "2D"
    // double **scoreSet = &score; // removed, this was unneeded and probably causing problems
    int size = 0;
    size = inputData( names, scores );
    for ( int i = 0; i < size; i++ ) {
        cout << *( names + i ) << endl;
    }
}

int inputData( string *&names, double **&scoreSet ) {
    int numStudents = 0;
    cout << "How many students do you have in the system? ";
    cin >> numStudents;
    while ( numStudents <= 0 ) {
        cout << "Invalid number of students. Please enter number of students: ";
        cin >> numStudents;
    }
    names = new string[numStudents];
    scoreSet = new double*[numStudents]; // allocate an array of pointers
    // cin.ignore( 10000, '\n' ); // Removed from here, placed inside loop
    for ( int i = 0; i < numStudents; i++ ) {
        cin.ignore( 10000, '\n' ); // placed here so that it always clears before getting the name
        int numTests = 0;
        cout << "Enter the student's name: ";
        getline( cin, names[i] );
        cout << "Enter how many tests " << names[i] << " took: "; // simplified
        cin >> numTests;
        scoreSet[i] = new double[numTests]; // simpliefied left hand side
        //cin.ignore( 10000, '\n' ); // not needed
        for ( int j = 0; j < numTests; j++ ) {
            cout << "Enter grade #" << j + 1 << ": ";
            cin >> scoreSet[i][j]; // simplified
        }
    }
    return numStudents;
}
answered on Stack Overflow Jan 27, 2020 by ChrisMM

User contributions licensed under CC BY-SA 3.0