Ali Samie Ali Samie - 1 month ago 16
C++ Question

heap corruption detected after normal block (#181)

(first of all sorry for English , cuz I'm not good at it)

I have written a code for magic-square which works fine and gives the true square.

When it is compiled and i run the program , there is nothing wrong.

But when it reaches to the

return 0
in the
main()
I get this error


heap corruption detected after normal block (#180)


I searched for it and I found out my
square
class didn't follow the rule of three(What is The Rule of Three?)

So I tried that and again got the error.

Here is my code.

#include<iostream>


using namespace std;

class square {

public:
//a n*n square which n=size
int size;
//a set of blocks in square which is declared
//by pointers cuz i couldn't simply write block[size][size]
int** block = new int*[size];
square(const int _size) {
size = _size;
for (int c = 0;c < size;c++) {
block[c] = new int[size];
}
//putting 0 value in all blocks
for (int i = 0; i < size;i++)
for (int j = 0;j < size;j++) {
block[i][j] = 0;
}
}
//distructor
~square() {
for (int c = 0; c < size; c++)
delete block[c];

delete block;
}
//copy constructor
square(const square& that) {
for (int c = 0; c < size; c++)
delete block[c];

delete block;
size = that.size;
block = new int*[size];
for (int c = 0;c < size;c++) {
block[c] = new int[size];
}
for (int i = 0; i < size;i++)
for (int j = 0;j < size;j++) {
block[i][j] = that.block[i][j];
}
}
//add or change the value of a block
void add_block(int &value, int i, int j) {
block[i][j] = value;
}
//get the value stored in a block
int get_block(int i, int j) {
return block[i][j];
}
//get the size of the square
int get_size() {
return size;
}
//display the square
void disp() {
for (int i = 0; i < size;i++) {
for (int j = 0;j < size;j++) {
cout << block[i][j]<<' ';
}
cout << endl;
}

}


};
//just to write clean code i made this function
//to get the size of the square from input
int intro() {
cout << "magic square" << endl;
cout << "what's the size of rows and columns?(just enter an integer and must be one of the following numbers)" << endl;
cout << "3 , 5 , 7 , ... , (2n+1)" << endl;
int s_size;
cin >> s_size;
while (s_size % 2 == 0) {
cout << "!!! must be one of the following numbers : 3 , 5 , 7 , ... , (2n+1) !!!" << endl;
cout << "enter again" << endl;
cin >> s_size;
}
return s_size;
}
//look for next valid block to add the next number
//and adding the next number
//the algorithm is go up.go left.if not filled before
//put new number. else go back to last position.go down.put the number.
void add_next_magic_block(square &s,int &v,int &i , int &j) {
int s_size = s.get_size();
int ii = i;
int jj = j;
if (i == 0)
i = s_size - 1;
else
i--;
if (j == s_size - 1)
j = 0;
else
j++;
if (s.get_block(i, j) == 0)
s.add_block(v, i, j);
else {
s.add_block(v, ++ii, jj);
i = ii;
j = jj;
}
}
//magic square which starts from [0][j/2]
//and ends when it reaches to the
//size*size
//which is the last number
void do_magic_square_on(square &s) {
int end = s.get_size()*s.get_size();
int count=1;
int i = 0;
int j = s.get_size() / 2;
s.add_block(count, 0, j);
count++;

while (count <= end) {
add_next_magic_block(s, count, i, j);
count++;
}
}


int main() {
int s_size = intro();
square my_s(s_size);

do_magic_square_on(my_s);

my_s.disp();
system("pause");
return 0;
}

Answer

Actually the error occurs when you try to allocate memory for block, here

int** block = new int*[size];

That's because your member-variable size is not initialized at this point of your code and contains garbage. My suggestion is to initialize both variables in the constructor, like this:

int size;
int** block
square(int _size) : size(_size), block(new int*[size]) {
    size = _size;
    for (int c = 0; c < size; c++) {
        block[c] = new int[size];
    }
    for (int i = 0; i < size; i++)
        for (int j = 0; j < size; j++) {
            block[i][j] = 0;
        }
}

Be aware of the fact that because in the code above I decided to initialize size and then use it to initialize block, size has to be defined before block. If you change the order of the declaration to something like

int** block
int size;

The code will be using uninitialized size again.

Comments