Hey all, the following code is run probably 15 times before my program freezes, the program gets into this function but never comes out lol CodeBlocks returns this:
Process terminated with status -2147483641 (2 minutes, 8 seconds)
Anyway, I'm super new to C++ and especially memory management lol tonight I realised I had a massive memory leak, I'm pretty sure this Matrix object was the cause of the problem since I was never "freeing" pMatrix. Anyway I added a destructor to free the allocated memory. That stuffed my program up because every time I passed a matrix object (a copy of the object) the function would deconstruct the object - took me a while to figure out that the pMatrix of the object and the "copied" object point to the same address. So now I'm passing all Matrix objects that I don't want deconstructed by reference (e.g. void test(Matrix& a)). But now I'm getting the problem I spoke about earlier lol this is fun but I'm sure I'll start getting frustrated soon haha
pMatrix[i] = (float*)malloc(columns * sizeof(**pMatrix)); ought to be: pMatrix[i] = (float*)malloc(columns * sizeof(*pMatrix));, but that shouldn't cause the program to crash.
I'd guess that you've gone off the end of you array while using Matrix elsewhere in the program.
Don't use a 2D array for this. There's no point in doing all of this allocation. It just makes allocation/deletion code messier and adds all sorts of overhead.
Multidimentional arrays are evil.
Use a 1D array:
1 2 3 4 5 6 7 8 9 10 11 12 13
float* pMatrix;
//..
pMatrix = newfloat[ nRows * nCols ]; // only need one new/malloc
// .. when you need to access [x][y], do the following instead:
return pMatrix[ (y*nCols) + x ];
// .. and cleanup is much easier:
delete[] pMatrix;
*Disch stabs multidimentional arrays with the vorpal dagger firedraco gave him*
Haha yeah I agree with you Disch, that is a really nice way of doing this! I'll change it over once I figure out what is going on here lol might as well learn something from this.
Next, kbw - although I'm sure you're correct, I don't quiet understand it, I thought:
pMatrix = (float**)malloc(rows * sizeof(*pMatrix)); This creates a column of pointers, so I'm using the corresponding sizeof statement.
pMatrix[i] = (float*)malloc(columns * sizeof(**pMatrix)); Each pointer, created above, now points to the memory address malloc returns here which is the first element of the row. The row is an array of floats, so wouldn't I want to allocate memory for columns * sizeof(float)? - Anyway, I'll just say again, I'm sure you're correct lol I've been programming in C++ for like 1 week haha I just think I have an "error" in my understanding.
Lastly, jsmith haha you're going to love this! I haven't "implemented a proper copy constructor and assignment operator", I had no idea I had to do that lol it was all working fine before I implemented this destructor (apart from the massive memory leak lol). What kind of things should I be doing here? Any links you could provide me with?
Haha I'll also ask this while I'm at it. Is it possible for me to stuff my computer up by running some of the programs I've been writing lately in C++ - like the one discussed in this post? Just wondering lol
Your copy constructor and assignment operator both need to make a "deep" copy of
the pointer / matrix. As it stands, the default one provided by the compiler is only a
"shallow" copy (ie, it copies the pointer, not what the pointer points to).
1 2 3 4 5 6 7 8 9
class Foo {
int* p;
public:
Foo( const Foo& f ) {
p = newint;
*p = *f.p;
}
// Assignment operator should do something very similar
};
Haha thanks jsmith! That will fix the problem I was having when passing the object to a function right? Since I was only passing a "shallow" copy when the function terminated it deleted the shallow copy which would run the decontructor and free the memory allocated to the pointer of both the original and the copy.
Yeah, jsmith that fixed the problem - runs again without freezing. Still got a memory leak - although the "flow rate" is much slower now. I was wondering if the following code could be a source of the problem:
See funcL() returns a Matrix object and as you can see from above the multiplication operation returns a Matrix object. Will the deconstructor for the returned objects ever get called?
You'll save yourself a Matrix copy with: Matrix Matrix::operator * (const Matrix &m) const
but it really should be an external function: Matrix operator*(const Matrix &a, const Matrix &b) const
The returned Matrix will be copied. So yes constructors and destructors will be called. It seems wastefull doesn't it?
On the other matter of your pointers. You want a 2D array of floats that you've chosen to implement as an array of an arrays of floats.
The inner array is an array of floats, float*.
The outer array is an array of an array of floats, float**.
So when you allocate the outer array, you want a float**.
And when you allocate the inner arrays, you want float*.
Got it?
It's kinder on the heap, cheaper to maintain, kinder to the CPU cache, and a bit simpler to use the method Disch proposed, a single block large enough to hold all the elements, then manually do the index calculations (rather than leaving it to the compiler).