C/C++ Irritating heap corruption error in VC++2005

  • Thread starter Thread starter qxcdz
  • Start date Start date
  • Tags Tags
    Error
AI Thread Summary
The discussion centers around a C++ matrix class implementation that encounters a heap corruption error during matrix addition. The primary issue arises from the incorrect allocation of memory in the constructor and the addition operator. Specifically, the constructor allocates memory for the data array using `(rows_ * cols_) - 1`, which results in insufficient space. Additionally, the addition operator creates a local `result` matrix that goes out of scope when the function returns, leading to the destructor being called prematurely and causing heap corruption.Furthermore, the main function attempts to assign a 5x5 matrix to a 3x6 matrix, which is incompatible and leads to out-of-bounds access when trying to read from `tst3`. To resolve these issues, the memory allocation should be corrected to `rows_ * cols_`, and the `result` matrix should be declared with a proper scope or returned by value to avoid the corruption. These changes successfully eliminate the errors and allow the code to function correctly.
qxcdz
Messages
8
Reaction score
0
'kay, I've been doing coasting along in C++, overloading operators, defining matrix arithmetic... Except, there's this error stopping my otherwise flawless addition function from working. When the function ends, it calls ~matrix(), probably for the temp variable inside the function, and the delete [] data_ corrupts the heap. How, I don't know, so I'm showing you guys in the hope that someone will spot what I've done wrong.

HelloWorld.cpp:
Code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include "matrix.h"

using namespace std;
typedef unsigned char byte;

int main(int argc, _TCHAR* argv[])
{
	matrix tst1(5,5);
	matrix tst2(5,5);
	matrix tst3(3,6);
	tst1(3,4)=56;
	tst3=tst2+tst1;
	int tst=tst3(3,4);
	cout << tst;

	return 0;
};

stdafx.h:
Code:
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once


#define WIN32_LEAN_AND_MEAN		// Exclude rarely-used stuff from Windows headers
#include <stdio.h>
#include <tchar.h>



// TODO: reference additional headers your program requires here

matrix.h:
Code:
#define MATRIX_TYPE unsigned char

using namespace std;
//typedef unsigned char byte; --no longer needed due to #define directive

class matrix
{
	MATRIX_TYPE* data_; //using underscores to distinguish internal variables -- worth changing the rest of the code?
	int rows_,cols_;
public:
	matrix(int rows, int cols); //constructor
	~matrix(); //destructor DUMMY

	MATRIX_TYPE& operator() (int row, int col); //subscript operator
	MATRIX_TYPE  operator() (int row, int col) const; // subscript operator for constants
	matrix operator+(matrix op1); //matrix addition
	matrix& operator=(const matrix& op1); //assignment of a matrix, to account for size differences
};

matrix::matrix(int rowin, int colin)
{
	if(rowin==0){rows_=1;}else{rows_=rowin;};
	if(colin==0){cols_=1;}else{cols_=rowin;};
	data_=new MATRIX_TYPE[(rows_*cols_)-1];
};

matrix::~matrix()
{
	delete[] data_;
};

MATRIX_TYPE& matrix::operator() (int row, int col)
{
	if(row<rows_ && col<cols_)
	{
		return data_[(cols_*row)+col];
	}else{
		cout << "index out of range for this array" << endl;
		return data_[0];
	};
};

MATRIX_TYPE  matrix::operator() (int row, int col) const
{
	if(row<rows_ && col<cols_)
	{
		return data_[(cols_*row)+col];
	}else{
		cout << "index out of range for this array" << endl;
		return data_[0];
	};
};

matrix& matrix::operator=(const matrix& op1)
{
	if(this != &op1) //must not be the same object!
	{
		delete[] data_; //get rid of the old data
		rows_=op1.rows_; // make this new matrix have the same dimensions as the old one
		cols_=op1.cols_;
		data_=new MATRIX_TYPE[(rows_*cols_)-1]; //reassign space for data

		for(int r=0;r<rows_;r++)
		{
			for(int c=0;c<cols_;c++)
			{
				data_[(cols_*r)+c]=op1(r,c); //copy data over from other matrix
			};
		};

	};
	return *this;
};

matrix matrix::operator +(matrix op1)
{
	if((op1.rows_==rows_)&&(op1.cols_==cols_))
	{
		matrix result(rows_,cols_);
		for(int r=0;r<rows_;r++)
		{
			for(int c=0;c<cols_;c++)
			{
				result(r,c)=op1(r,c)+data_[(cols_*r)+c]; // fill result matrix with sums
			};
		};
		return result; // this line keeps causing a heap corruption!
	}else{
		cout << "matricies are not of equal dimension" << endl;
		matrix ret(1,1);
		return ret;
	};
};
 
Technology news on Phys.org
The OP hasn't been around in years, but others might benefit from my analysis of this code.

The most obvious problem is one statement in main():
C:
int main(int argc, _TCHAR* argv[])
{
    matrix tst1(5,5);
    matrix tst2(5,5);
    matrix tst3(3,6);
    tst1(3,4)=56;
    tst3=tst2+tst1;    // <---- Problem here
    int tst=tst3(3,4);
    cout << tst;

    return 0;
};
In the line with the comment you are 1) adding two arrays of the same size (that's fine), but 2) attempting to store the contents of a 5 x 5 matrix in a 3 x 6 matrix. This won't work.

There is also a problem in the line that follows, where you are attempting to read the value in tst3(3, 4), but the tst3 array has only 3 rows that have indexes of 0, 1, and 2.

The less obvious, but more difficult problems are in your constructor and in your addition operator code.
First, the constructor:
C:
matrix::matrix(int rowin, int colin)
{
    if (rowin == 0) { rows_ = 1; }
    else { rows_ = rowin; };
    if (colin == 0) { cols_ = 1; }
    else { cols_ = rowin; };
    data_ = new MATRIX_TYPE[(rows_*cols_) - 1];  // <=== Problem here
};
In the commented line, your heap matrix, data_, is too small. Inside the brackets should be rows_ * cols_. The same problem is present in your assignment operator code.

In your addition operator:
C:
matrix matrix::operator +(matrix op1)
{
    if ((op1.rows_ == rows_) && (op1.cols_ == cols_))
    {
        matrix result(rows_, cols_);              // <=== Problem here
        for (int r = 0; r < rows_; r++)
        {
            for (int c = 0; c < cols_; c++)
            {
                result(r, c) = op1(r, c) + data_[(cols_*r) + c]; // fill result matrix with sums
            };
        };
        return result; // this line keeps causing a heap corruption!
    }
    else {
        cout << "matricies are not of equal dimension" << endl;
        matrix ret(1, 1);
        return ret;
    };
};
Your result variable is an automatic variable (allocated on the stack) that goes out of scope as soon as this function returns. When result goes out of scope, the matrix destructor is called before the contents of the array sum can be copied over to the tst3 array in main(). One fix for this is to declare result to be static.

BTW, by making the changes I described, I was able to get the code to work.
 
Last edited:
Dear Peeps I have posted a few questions about programing on this sectio of the PF forum. I want to ask you veterans how you folks learn program in assembly and about computer architecture for the x86 family. In addition to finish learning C, I am also reading the book From bits to Gates to C and Beyond. In the book, it uses the mini LC3 assembly language. I also have books on assembly programming and computer architecture. The few famous ones i have are Computer Organization and...
I have a quick questions. I am going through a book on C programming on my own. Afterwards, I plan to go through something call data structures and algorithms on my own also in C. I also need to learn C++, Matlab and for personal interest Haskell. For the two topic of data structures and algorithms, I understand there are standard ones across all programming languages. After learning it through C, what would be the biggest issue when trying to implement the same data...

Similar threads

Replies
2
Views
3K
Replies
22
Views
3K
Replies
23
Views
2K
Replies
5
Views
3K
Replies
8
Views
2K
Replies
3
Views
2K
Replies
23
Views
2K
Back
Top