Hi all,
well allthough I'm new to C++ I've done my share of development in more user friendly environments, mainly C#.
Anyhow I want to learn C++ as mainly personal interest as my professional life will be focused primarly in .NET development whenever it is needed.
To learn the basics of the language I'm starting with a real easy Math class that will initially implement a Matrix (no templates). Nothing fancy but an easy place to start to at least start learning Object Oriented programming in C++ like any other.
Well the thing is that I'm completely stumped with an error I'm getting. I've created a simple Win32 console app that links my FastMath.dll and uses the FMatrix class defined inside. Test app code is as simple as it can get, it only instantiates one FMatrix and then deletes it, and something that simple is giving me a runtime error. Here's the code in the tesp app:
#include "stdafx.h"
#include "FMatrix.h"
#include <iostream>
using namespace FastMath;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
FMatrix *a=new FMatrix(5);
cout << "A is a [" << a->GetRowCount() << "x" << a->GetColumnCount() << "] matrix." << endl;
delete a;
return 0;
}
Ok the error I'm getting is when executing "delete a":
Windows has triggered a breakpoint in Tester.exe.
This may be due to a corruption of the heap, and indicates a bug in Tester.exe or any of the DLLs it has loaded.
The output window may have more diagnostic information
If I try to continue I get the same error once and then succesive Assertion Failed error messages: "Expression: _CrtIsValidHeapPointer(pUserData)" and if I ignore that I get a HEAP CORRUPTION DETECTED error message "CRT detected that the application wrote to memory after end of heap buffer."
I really do not understand what I'm doing wrong in my FMatrix file. I'm including header and source files below:
FMatrix.h
#ifdef FASTMATH_EXPORTS
#define FASTMATH_API __declspec(dllexport)
#else
#define FASTMATH_API __declspec(dllimport)
#endif
#pragma once
#include "StdAfx.h"
namespace FastMath
{
class FASTMATH_API FMatrix
{
private:
int rw,cl;
double *val;
FMatrix(void);
FMatrix(unsigned int,bool);
FMatrix(unsigned int,unsigned int,bool);
void initMatrix(unsigned int,unsigned int,bool);
void destroy(void);
public:
FMatrix(const FMatrix&);
FMatrix(unsigned int);
FMatrix(unsigned int,unsigned int);
FMatrix(unsigned int,unsigned int,double**);
~FMatrix(void);
static FMatrix* CreateIdentity(unsigned int);
static FMatrix* CreateFull(unsigned int,unsigned int,double);
static FMatrix* CreateRandomIntMatrix(unsigned int,unsigned int,int,int);
static FMatrix* CreateRandomDblMatrix(unsigned int,unsigned int,double,double);
double GetItem(unsigned int,unsigned int) const;
void SetItem(unsigned int,unsigned int,double);
int GetRowCount() const;
int GetColumnCount() const;
static bool AreSameSize(const FMatrix&,const FMatrix&);
FMatrix& operator =(const FMatrix&);
FMatrix& operator -() const;
FMatrix& operator +(const FMatrix&) const;
FMatrix& operator -(const FMatrix&) const;
FMatrix& operator *(double) const;
FMatrix& operator *(const FMatrix&) const;
FMatrix& operator !() const;
bool operator ==(const FMatrix&) const;
bool operator !=(const FMatrix&) const;
};
}
FMatrix.cpp
#include "StdAfx.h"
#include "FMatrix.h"
#include "time.h"
#include <cstdlib>
#include <iostream>
using namespace FastMath;
using namespace std;
void FMatrix::initMatrix(unsigned int r,unsigned int c, bool initValues)
{
rw=r;
cl=c;
val=new double[rw*cl];
#ifdef _DEBUG
cout <<"++ Matrix created." << endl;
#endif
if (initValues)
{
for (int i=0;i<rw;i++)
{
for (int j=0;j<cl;j++)
*(val+i*cl+j)=0;
}
}
}
FMatrix::FMatrix()
{
}
FMatrix::FMatrix(unsigned int dim,bool initValues)
{
initMatrix(dim,dim,initValues);
}
FMatrix::FMatrix(unsigned int rows,unsigned int columns,bool initValues)
{
initMatrix(rows,columns,initValues);
}
FMatrix::FMatrix(unsigned int dim)
{
initMatrix(dim,dim,true);
}
FMatrix::FMatrix(unsigned int rows, unsigned int columns)
{
initMatrix(rows,columns,true);
}
FMatrix::FMatrix(const FMatrix &m)
{
initMatrix(m.rw,m.cl,false);
for (int i=0;i<rw;i++)
{
for (int j=0;j<cl;j++)
*(val+i*cl+j)=*(m.val+i*cl+j);
}
}
FMatrix::~FMatrix()
{
destroy();
}
void FMatrix::destroy()
{
delete[] val;
#ifdef _DEBUG
cout << "-- Matrix destroyed." << endl;
#endif
}
FMatrix* FMatrix::CreateIdentity(unsigned int dim)
{
FMatrix *t=new FMatrix(dim,false);
double* pTval=t->val;
int c=t->cl;
for (register int i=0;i<t->rw;i++)
{
for (register int j=0;j<c;j++)
{
if (j==i)
*(pTval+i*c+j)=1;
else
*(pTval+i*c+j)=0;
}
}
pTval=NULL;
return t;
}
FMatrix* FMatrix::CreateFull(unsigned int rows, unsigned int columns, double value)
{
FMatrix *t=new FMatrix(rows,columns,false);
double* pTval=t->val;
int c=t->cl;
for (register int i=0;i<t->rw;i++)
{
for (register int j=0;j<c;j++)
{
*(pTval+i*c+j)=value;
}
}
pTval=NULL;
return t;
}
FMatrix* FMatrix::CreateRandomIntMatrix(unsigned int rows, unsigned int columns, int lowest, int highest)
{
FMatrix *t=new FMatrix(rows,columns,false);
double* pTval=t->val;
int c=t->cl;
SYSTEMTIME lp;
GetSystemTime(&lp);
srand(rand()*(unsigned int)lp.wMilliseconds);
for (register int i=0;i<t->rw;i++)
{
for (register int j=0;j<c;j++)
{
*(pTval+i*c+j)=int(lowest+double(rand())/RAND_MAX*(highest-lowest)+.5);
}
}
pTval=NULL;
return t;
}
FMatrix* FMatrix::CreateRandomDblMatrix(unsigned int rows, unsigned int columns, double lowest, double highest)
{
FMatrix *t=new FMatrix(rows,columns,false);
double* pTval=t->val;
int c=t->cl;
SYSTEMTIME lp;
GetSystemTime(&lp);
srand((unsigned int)lp.wMilliseconds);
for (register int i=0;i<t->rw;i++)
{
for (register int j=0;j<c;j++)
{
*(pTval+i*c+j)=lowest+double(rand())/RAND_MAX*(highest-lowest);
}
}
pTval=NULL;
return t;
}
FMatrix& FMatrix::operator =(const FMatrix &m)
{
if (this!=&m)
{
double* pMval=m.val;
rw=m.rw;
cl=m.cl;
destroy();
initMatrix(rw,cl,false);
for (register int i=0;i<rw;i++)
{
for (register int j=0;j<cl;j++)
{
*(val+i*cl+j)=*(pMval+i*cl+j);
}
}
pMval=NULL;
}
return *this;
}
FMatrix& FMatrix::operator -() const
{
FMatrix *t=new FMatrix(rw,cl,false);
double* pTval=t->val;
for (register int i=0;i<rw;i++)
{
for (register int j=0;j<cl;j++)
{
*(pTval+i*cl+j)=-*(val+i*cl+j);
}
}
pTval=NULL;
return *t;
}
FMatrix& FMatrix::operator +(const FMatrix &m) const
{
if (!AreSameSize(*this,m))
{
throw exception("Matrix can not be added. Dimensions do not match.");
}
FMatrix *t=new FMatrix(rw,cl,false);
double* pTval=t->val;
double* pMval=m.val;
for (register int i=0;i<rw;i++)
{
for (register int j=0;j<cl;j++)
{
*(pTval+i*cl+j)=*(val+i*cl+j)+*(pMval+i*cl+j);
}
}
pTval=NULL;
pMval=NULL;
return *t;
}
FMatrix& FMatrix::operator -(const FMatrix &m) const
{
if (!AreSameSize(*this,m))
throw invalid_argument("Matrix can not be added. Dimensions do not match.");
FMatrix *t=new FMatrix(rw,cl,false);
double* pTval=t->val;
double* pMval=m.val;
for (register int i=0;i<rw;i++)
{
for (register int j=0;j<cl;j++)
{
*(pTval+i*cl+j)=*(val+i*cl+j)-*(pMval+i*cl+j);
}
}
pTval=NULL;
pMval=NULL;
return *t;
}
FMatrix& FMatrix::operator *(double d) const
{
FMatrix *t=new FMatrix(rw,cl,false);
double* pTval=t->val;
for (register int i=0;i<rw;i++)
{
for (register int j=0;j<cl;j++)
{
*(pTval+i*cl+j)=*(val+i*cl+j)*d;
}
}
pTval=NULL;
return *t;
}
FMatrix& FMatrix::operator !() const
{
FMatrix *t=new FMatrix(cl,rw,false);
double* pTval=t->val;
for (register int i=0;i<rw;i++)
{
for (register int j=0;j<cl;j++)
{
*(pTval+j*rw+i)=*(val+i*cl+j);
}
}
pTval=NULL;
return *t;
}
bool FMatrix::operator ==(const FMatrix &m) const
{
if (!AreSameSize(*this,m))
return false;
double *pMval=m.val;
for (register int i=0;i<rw;i++)
{
for (register int j=0;j<cl;j++)
{
if (*(pMval+i*cl+j)!=*(val+i*cl+j))
return false;
}
}
pMval=NULL;
return true;
}
bool FMatrix::operator !=(const FMatrix &m) const
{
return !(*this==m);
}
double FMatrix::GetItem(unsigned int r, unsigned int c) const
{
return *(val+r*cl+c);
}
void FMatrix::SetItem(unsigned int r, unsigned int c, double value)
{
*(val+r*cl+c)=value;
}
int FMatrix::GetRowCount() const
{
return rw;
}
int FMatrix::GetColumnCount() const
{
return cl;
}
bool FMatrix::AreSameSize(const FMatrix &m1, const FMatrix &m2)
{
return (m1.rw==m2.rw)&&(m1.cl==m2.cl);
}
I'm really confused because I dont know what I'm doing wrong. The thing is if I use in the App test the static constructors (CreateRandomIntMatrix for example) and I dont have to manually delete them from the app test everything works greate and the destructor of my two matrixes is called all by itself. But when I explecitly instantiate with the new operator in my app test and thus have to delete them myself in that same app I get the errors described above.
Any help plz?
P.D. Sorry about the long post.
|