Hello,
I have a project that needs to implement a Safe Array which is an Array that has bounds checking. On top of that I need to create a "Matrix" class which implements 2D which is basically a Safe array within a Safe array. This is also templatized.

The problem is it compiles fine with my eclipse but when I try to compile
in Unix it gives me this error: *** glibc detected *** double free or corruption: 0x0937d008 ***

Can someone check my code to see if there is anything wrong with it?

Also: Does anyone know why when it calls my copy constructor when making the 2D Safe Array? I have to comment it out inorder for it to work.

Here is my code:

#include <iostream>
#include <stdlib.h>
#include <assert.h>

using namespace std;

template <class T>
class SA{
private:
	int low, high;
	T* p;
public:
	// default constructor 
	SA(){
		low = 0; 
		high = -1;
		p = NULL;
	}//constructor
	
	// 2 parameter constructor SA x(10,20); 
	SA(int l, int h){
		if( (h - l + 1) <= 0 ){
		cout << "constructor error in bounds definition" << endl;
		exit(1);
		}//if
		low = l;
		high = h;
		p = new T[h-l+1];
	}//2 parameter constructor
	
	// single parameter constructor
	// SA x(10); and getting an array x indexed from 0 to 9
	SA(int i){
		low = 0; 
		high = i - 1;
		p = new T[i];
	}//singple parameter constructor
	
	/*
	// copy constructor for pass by value and initialization
	SA(const SA & s){
		int size = s.high - s.low + 1;
		p = new T[size];
			for(int i=0; i<size; i++)
				p[i] = s.p[i];
		low = s.low;
		high = s.high;
	}//copy constructor
	*/
	
	// destructor
	~SA(){
		delete [] p;
	}//destructor

	//overloaded [] lets us write
	//SA x(10,20); x[15]= 100;
	T& operator[](int i){
		if(i < low || i > high){
			cout << "index "<< i << " out of range" << endl;
			exit(1);
		}//if
		return p[i-low];
	}//overloaded [] operator
	
	
	// overloaded assignment lets us assign one SA to another
	SA & operator=(const SA s){
		if(this == &s)
			return *this;
		delete [] p;
		int size = s.high - s.low + 1;
		p = new T[size];
			for(int i = 0; i < size; i++)
				p[i] = s.p[i];
		low = s.low;
		high = s.high;
		return *this;
	}//overloaded = operator

	
	// overloads << so we can directly print SAs
	friend ostream& operator<<(ostream& os, SA s){
		int size = s.high - s.low + 1;
            for(int i = 0; i < size; i++)
            	cout << s.p[i] << endl;
        return os;
    };

};//class SafeArray


//Matrix class
template <class T>
class Matrix{
private:
	SA < SA<T> > mat;
	
public:
	
	//2 parameter constructor
	Matrix(int row, int col){
		mat = SA< SA<T> >(0, row-1);
			for(int i = 0; i < row; i++){
				mat[i] = SA<T>(0, col-1);
			}//for
	}//construct for 2 parameters
	
	//4 parameter constructor
	Matrix(int r1, int r2, int c1, int c2){
		mat = SA< SA<T> >(r1, r2-1);
			for(int i = r1; i < r2; i++)
				mat[i] = SA<T>(c1, c2-1);
	}//4 parameter constructor
	
	SA<T> operator[](int r){
		return(mat[r]);
	}//operator[] overload
	
	
};//class Matrix



int main(){
	Matrix <int>arr(5,10);//create 2D array of 5 rows and 10 cols
	Matrix <int>arr2(10,20,100,200);//create 2D array of 10 rows from 10-19 and 100 cols from 100-199
	
	arr[3][8]=1234;//test
	cout << arr[3][8] << endl;
	
	arr2[12][155]=1111;//test
	cout << arr2[12][155] << endl;
	
	//testing out of bounds
	arr[5][6]=1;
	int i = arr2[22][200];

return 0;

}//main

> double free or corruption: 0x0937d008
With the copy constructor commented out, you have tons of alias pointers floating around. The destructor assumes that a copy constructor exists and allocates a unique pointer, but it doesn't.

> Can someone check my code to see if there is anything wrong with it?
You pass by value when you should be passing by reference. Basically anywhere SA<T> is passed or returned, it should be either a reference or a const reference.

> double free or corruption: 0x0937d008
With the copy constructor commented out, you have tons of alias pointers floating around. The destructor assumes that a copy constructor exists and allocates a unique pointer, but it doesn't.

> Can someone check my code to see if there is anything wrong with it?
You pass by value when you should be passing by reference. Basically anywhere SA<T> is passed or returned, it should be either a reference or a const reference.

Hi Thanks for replying!

But when I uncomment the copy constructor, it doesn't seem to work when I do
Matrix <int>arr(5,10);
arr[3][8]=1234;

because it calls the copy constructor.
Is there a way to fix this?

and thanks for telling to replace passing for value for reference, will make the changes.

> Is there a way to fix this?
Sure, read the rest of Edward's reply and fix the pass-by-value problems. :D This in particular:

SA<T> operator[](int r){

The copy constructor is always called to create a new object for the return value of operator[] in your matrix class.

> Is there a way to fix this?
Sure, read the rest of Edward's reply and fix the pass-by-value problems. :D This in particular:

SA<T> operator[](int r){

The copy constructor is always called to create a new object for the return value of operator[] in your matrix class.

Wow, awsome! Thanks, you taught me something. If I don't pass by reference, the copy constructor will always be called because it is passed in by value and need a copy.


I have 1 more question:
We know that *(*(k+i)+j) is equivalent to k[j].
Is there a way to implement the same thing but with my matrix class?
Is there a pointer * overloading?
Can you point me or hint me on a way to accomplish this?

> We know that *(*(k+i)+j) is equivalent to k[j].
> Is there a way to implement the same thing but with my matrix class?
Sure, but you have to do it by overloading all of the required operators. SA is a pointer under the hood so it's pretty easy by adding an implicit conversion operator to each class:

template <typename T>
SA<T>::operator T*() { return p; }

template <typename T>
Matrix<T>::operator SA<T>*() { return mat; }

> We know that *(*(k+i)+j) is equivalent to k[j].
> Is there a way to implement the same thing but with my matrix class?
Sure, but you have to do it by overloading all of the required operators. SA is a pointer under the hood so it's pretty easy by adding an implicit conversion operator to each class:

template <typename T>
SA<T>::operator T*() { return p; }

template <typename T>
Matrix<T>::operator SA<T>*() { return mat; }

Hmm, it seemed to compile fine but when I ran it, it gave me an error of "Segmentation fault"

I added your code.
added

operator SA<T>*() {return mat;}//operator * overload

in my matrix class
and added

operator T*(){return p;}//operator * overload

in my Safe Array class

Matrix <int>arr2(10,20,100,200);
	//testing *(*(k+i)+j) is equivalent to k[i][j]
	cout << "testing *(*(k+i)+j) is equivalent to k[i][j]" << endl;
	cout << "testing arr2[12][155] which is *(*(arr2+12)+155)" << endl;
	int test = *(*(arr2+12)+155);
	cout << test;

Anything I did wrong?

> Anything I did wrong?
You forgot to take the index shift into account. The matrix class supports N-based arrays, but the internal memory is still 0-based. You should subtract the low end of the range from each index:

Matrix <int>arr2(10,20,100,200);
//testing *(*(k+i)+j) is equivalent to k[i][j]
cout << "testing *(*(k+i)+j) is equivalent to k[i][j]" << endl;
cout << "testing arr2[12][155] which is *(*(arr2+2)+55)" << endl;
*(*(arr2+2)+55) = 1234;
int test = *(*(arr2+2)+55);
cout << test <<'\n';

Im sorry, Im not too sure what you mean. Internal memory? and what you mean by the low end of the range?

Would I modify the code for the operator*?

> Im sorry, Im not too sure what you mean.
If you create an object, SA<int>(10, 20), you can access index 15 even though there are only 10 elements. That's because the SA class forces the index back into what it should be behind the scenes:

return p[i-low];

The operator* that Edward showed you doesn't include any of that adjustment logic so you have to use the correct indexes from the start. I can't think of a safe way to let you use the "fake" range without a lot of extra code.

> Would I modify the code for the operator*?
No, you would use the [] operator and avoid accessing the SA class' internal pointer.

> Im sorry, Im not too sure what you mean.
If you create an object, SA<int>(10, 20), you can access index 15 even though there are only 10 elements. That's because the SA class forces the index back into what it should be behind the scenes:

return p[i-low];

The operator* that Edward showed you doesn't include any of that adjustment logic so you have to use the correct indexes from the start. I can't think of a safe way to let you use the "fake" range without a lot of extra code.

> Would I modify the code for the operator*?
No, you would use the [] operator and avoid accessing the SA class' internal pointer.

Oh, I get what you mean. It works if I create without an offset such as SA<int>(5,5).

When you mean "safe way", there is a way but it would be dangerous to put in it?

But Thanks so much for helping me this far.
I still have part 2 of this project to finish and if I come across any more troubles Ill post again. Thanks!!

> When you mean "safe way", there is a way but it would be dangerous to put in it?
Sure, you can subtract the pointer itself from within SA's operator* and that will shift the range before your arithmetic gets to it:

operator T*() { return p - low; }

Technically, it's not safe even to calculate the address of a pointer outside of the allocated memory, so the above code falls into the realm of Bad Codeā„¢.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.