0

So for an assignment I have to create a program that will create magic squares when the user inputs an odd number, I have most of the program done but for some reason when I try to populate the squares I get Unhandled exception at 0x00326315 in magic square.exe: 0xC0000005: Access violation reading location 0x00000000

I'm using classes and have the declaration for square as int **square;

Here is the code

#include<iostream>
#include<iomanip>
#include"MagicSquare.h"

using namespace std;

MagicSquare::MagicSquare(): size(0), maxNum(0), row(0), col(0), curNum(0) //Constructor initialize variables
{
}

MagicSquare::~MagicSquare()                             //Destructor 
{
for (int i = 0; i < size; i++)
{
    delete[] square[i];
}
delete[] square;                                                                            //Delete the dynamically allocated memory
}
void MagicSquare::getSize() //Get the size of the magic square
{
    cout << "Please enter an odd number for the number of rows/columns: ";
    cin >> size;
    while (size % 2 == 0) //Check to see if the number entered is odd
    {
        cout << "The number you entered is not odd, please enter an odd number: ";
        cin >> size;
    }

    int **square = new (nothrow) int*[size];
    for (int i = 0; i < size; i++)
    {
        square[i] = new (nothrow) int[size];
    }
    maxNum = size * size;
    iCount = new (nothrow) int[size];
    jCount = new (nothrow) int[size];
}

void MagicSquare::populateSquare()
{
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            square[i][j] = 0;     //This is where the error occurs
        }
    }
    curNum = 1;
    col = (size - 1) / 2;
    square[row][col] = curNum;
    curNum += 1;
    for (int i = 1; i <= maxNum; i++)
    {
        row = row - 1;
        col = col + 1;
        if (col >= size)
            col = 0;
        if (row < 0)
            row = size - 1;
        square[row][col] = curNum;
        curNum += 1;
    }
}

Header file

class MagicSquare
{
private:
int **square;
int size;
int maxNum;
int row;
int col;
int curNum;
int *iCount;
int *jCount;

public:
MagicSquare();
~MagicSquare();
void getSize();
void populateSquare();
void printSquare();
};

source file

#include"MagicSquare.h"
#include<iostream>


using namespace std;


int main() 
{
MagicSquare mySquare;

int choice = 1;
while (choice == 1)
{
    mySquare.getSize();
    mySquare.populateSquare();
    mySquare.printSquare();

    cout << "\n\nWould you like to create another magic square? 1 for yes, 0 for no: ";
    cin >> choice;
    while (choice != 1 || choice != 0)
    {
        cout << "\nInvalid input: \nWould you like to create another magic square? 1 for yes, 0 for no: ";
        cin >> choice;
    }
}

system("pause");

return 0;
}
8
  • 3
    Why do you use new (nothrow) without checking the returned value? Also, give us something that compiles. Commented Sep 23, 2014 at 20:22
  • Teacher requires it, I don't normally use (nothrow) Commented Sep 23, 2014 at 20:23
  • 2
    Does your teacher REALLY say that you should not check the result from the new call, or simply that you should use nothrow? If that is the case, you should SERIOUSLY consider looking for another point of education, as it's a bit insane. (I was just about to write something similar to what tillaert wrote when it popped up) Commented Sep 23, 2014 at 20:25
  • @James Boyden Then you have to check whether the value is not equal to NULL. Because your new might fail. Check the value of size, it might be very large. Commented Sep 23, 2014 at 20:26
  • "Access violation reading location 0x00000000" this is a null pointer de-ref, use the debugger Commented Sep 23, 2014 at 20:26

2 Answers 2

2

You are defining a local variable called square in your getSize() method here:

int **square = new (nothrow) int*[size];.

So you make space for the local variable but never for the class's field.

Change this line to

square = new (nothrow) int*[size];

Also seriously consider checking the results of the calls.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that worked. I'm looking up how to check the results now.
1

Access violation reading location 0x00000000 is telling you, that you are trying to access a NULL-pointer. A reason could be, that at least one call of new failed. you should check when allocating the array:

int **square = new (nothrow) int*[size];
if(square == NULL)
    //Handle error here
for (int i = 0; i < size; i++)
{
    square[i] = new (nothrow) int[size];
    if(square == NULL)
        //Handle error here
}

But i guess thats not the reason. If I saw it right, you have two functions:

void MagicSquare::getSize() 
void MagicSquare::populateSquare()

But the int **square is created in getSize, so if you call populate square, this variable does not exist anymore.

if your class is:

class MagicSquare
{
private:
    int **square;
public:
    //Methods
}

in getSize you have to store the address in the classes member variable, not a local one you just created:

square = new (nothrow) int*[size]; //without int **

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.