Safe Array within a Safe Array Implementation

Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Oct 2007
Posts: 58
Reputation: ff4930 is an unknown quantity at this point 
Solved Threads: 2
ff4930 ff4930 is offline Offline
Junior Poster in Training

Safe Array within a Safe Array Implementation

 
0
  #1
Jun 9th, 2008
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:
  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4.  
  5. using namespace std;
  6.  
  7. template <class T>
  8. class SA{
  9. private:
  10. int low, high;
  11. T* p;
  12. public:
  13. // default constructor
  14. SA(){
  15. low = 0;
  16. high = -1;
  17. p = NULL;
  18. }//constructor
  19.  
  20. // 2 parameter constructor SA x(10,20);
  21. SA(int l, int h){
  22. if( (h - l + 1) <= 0 ){
  23. cout << "constructor error in bounds definition" << endl;
  24. exit(1);
  25. }//if
  26. low = l;
  27. high = h;
  28. p = new T[h-l+1];
  29. }//2 parameter constructor
  30.  
  31. // single parameter constructor
  32. // SA x(10); and getting an array x indexed from 0 to 9
  33. SA(int i){
  34. low = 0;
  35. high = i - 1;
  36. p = new T[i];
  37. }//singple parameter constructor
  38.  
  39. /*
  40. // copy constructor for pass by value and initialization
  41. SA(const SA & s){
  42. int size = s.high - s.low + 1;
  43. p = new T[size];
  44. for(int i=0; i<size; i++)
  45. p[i] = s.p[i];
  46. low = s.low;
  47. high = s.high;
  48. }//copy constructor
  49. */
  50.  
  51. // destructor
  52. ~SA(){
  53. delete [] p;
  54. }//destructor
  55.  
  56. //overloaded [] lets us write
  57. //SA x(10,20); x[15]= 100;
  58. T& operator[](int i){
  59. if(i < low || i > high){
  60. cout << "index "<< i << " out of range" << endl;
  61. exit(1);
  62. }//if
  63. return p[i-low];
  64. }//overloaded [] operator
  65.  
  66.  
  67. // overloaded assignment lets us assign one SA to another
  68. SA & operator=(const SA s){
  69. if(this == &s)
  70. return *this;
  71. delete [] p;
  72. int size = s.high - s.low + 1;
  73. p = new T[size];
  74. for(int i = 0; i < size; i++)
  75. p[i] = s.p[i];
  76. low = s.low;
  77. high = s.high;
  78. return *this;
  79. }//overloaded = operator
  80.  
  81.  
  82. // overloads << so we can directly print SAs
  83. friend ostream& operator<<(ostream& os, SA s){
  84. int size = s.high - s.low + 1;
  85. for(int i = 0; i < size; i++)
  86. cout << s.p[i] << endl;
  87. return os;
  88. };
  89.  
  90. };//class SafeArray
  91.  
  92.  
  93. //Matrix class
  94. template <class T>
  95. class Matrix{
  96. private:
  97. SA < SA<T> > mat;
  98.  
  99. public:
  100.  
  101. //2 parameter constructor
  102. Matrix(int row, int col){
  103. mat = SA< SA<T> >(0, row-1);
  104. for(int i = 0; i < row; i++){
  105. mat[i] = SA<T>(0, col-1);
  106. }//for
  107. }//construct for 2 parameters
  108.  
  109. //4 parameter constructor
  110. Matrix(int r1, int r2, int c1, int c2){
  111. mat = SA< SA<T> >(r1, r2-1);
  112. for(int i = r1; i < r2; i++)
  113. mat[i] = SA<T>(c1, c2-1);
  114. }//4 parameter constructor
  115.  
  116. SA<T> operator[](int r){
  117. return(mat[r]);
  118. }//operator[] overload
  119.  
  120.  
  121. };//class Matrix
  122.  
  123.  
  124.  
  125. int main(){
  126. Matrix <int>arr(5,10);//create 2D array of 5 rows and 10 cols
  127. Matrix <int>arr2(10,20,100,200);//create 2D array of 10 rows from 10-19 and 100 cols from 100-199
  128.  
  129. arr[3][8]=1234;//test
  130. cout << arr[3][8] << endl;
  131.  
  132. arr2[12][155]=1111;//test
  133. cout << arr2[12][155] << endl;
  134.  
  135. //testing out of bounds
  136. arr[5][6]=1;
  137. int i = arr2[22][200];
  138.  
  139. return 0;
  140.  
  141. }//main
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 351
Reputation: Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about 
Solved Threads: 62
Radical Edward's Avatar
Radical Edward Radical Edward is offline Offline
Posting Whiz

Re: Safe Array within a Safe Array Implementation

 
0
  #2
Jun 9th, 2008
> 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.
If at first you don't succeed, keep on sucking until you do succeed.
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 58
Reputation: ff4930 is an unknown quantity at this point 
Solved Threads: 2
ff4930 ff4930 is offline Offline
Junior Poster in Training

Re: Safe Array within a Safe Array Implementation

 
0
  #3
Jun 9th, 2008
Originally Posted by Radical Edward View Post
> 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.
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 351
Reputation: Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about 
Solved Threads: 62
Radical Edward's Avatar
Radical Edward Radical Edward is offline Offline
Posting Whiz

Re: Safe Array within a Safe Array Implementation

 
0
  #4
Jun 9th, 2008
> Is there a way to fix this?
Sure, read the rest of Edward's reply and fix the pass-by-value problems. This in particular:
  1. 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.
If at first you don't succeed, keep on sucking until you do succeed.
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 58
Reputation: ff4930 is an unknown quantity at this point 
Solved Threads: 2
ff4930 ff4930 is offline Offline
Junior Poster in Training

Re: Safe Array within a Safe Array Implementation

 
0
  #5
Jun 9th, 2008
Originally Posted by Radical Edward View Post
> Is there a way to fix this?
Sure, read the rest of Edward's reply and fix the pass-by-value problems. This in particular:
  1. 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[i][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?
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 351
Reputation: Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about 
Solved Threads: 62
Radical Edward's Avatar
Radical Edward Radical Edward is offline Offline
Posting Whiz

Re: Safe Array within a Safe Array Implementation

 
0
  #6
Jun 9th, 2008
> We know that *(*(k+i)+j) is equivalent to k[i][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:
  1. template <typename T>
  2. SA<T>::operator T*() { return p; }
  3.  
  4. template <typename T>
  5. Matrix<T>::operator SA<T>*() { return mat; }
If at first you don't succeed, keep on sucking until you do succeed.
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 58
Reputation: ff4930 is an unknown quantity at this point 
Solved Threads: 2
ff4930 ff4930 is offline Offline
Junior Poster in Training

Re: Safe Array within a Safe Array Implementation

 
0
  #7
Jun 9th, 2008
Originally Posted by Radical Edward View Post
> We know that *(*(k+i)+j) is equivalent to k[i][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:
  1. template <typename T>
  2. SA<T>::operator T*() { return p; }
  3.  
  4. template <typename T>
  5. 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
  1. operator SA<T>*() {return mat;}//operator * overload
in my matrix class
and added
  1. operator T*(){return p;}//operator * overload
in my Safe Array class

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

Anything I did wrong?
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 351
Reputation: Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about 
Solved Threads: 62
Radical Edward's Avatar
Radical Edward Radical Edward is offline Offline
Posting Whiz

Re: Safe Array within a Safe Array Implementation

 
0
  #8
Jun 9th, 2008
> 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:
  1. Matrix <int>arr2(10,20,100,200);
  2. //testing *(*(k+i)+j) is equivalent to k[i][j]
  3. cout << "testing *(*(k+i)+j) is equivalent to k[i][j]" << endl;
  4. cout << "testing arr2[12][155] which is *(*(arr2+2)+55)" << endl;
  5. *(*(arr2+2)+55) = 1234;
  6. int test = *(*(arr2+2)+55);
  7. cout << test <<'\n';
If at first you don't succeed, keep on sucking until you do succeed.
Reply With Quote Quick reply to this message  
Join Date: Oct 2007
Posts: 58
Reputation: ff4930 is an unknown quantity at this point 
Solved Threads: 2
ff4930 ff4930 is offline Offline
Junior Poster in Training

Re: Safe Array within a Safe Array Implementation

 
0
  #9
Jun 9th, 2008
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*?
Reply With Quote Quick reply to this message  
Join Date: May 2008
Posts: 351
Reputation: Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about Radical Edward has a spectacular aura about 
Solved Threads: 62
Radical Edward's Avatar
Radical Edward Radical Edward is offline Offline
Posting Whiz

Re: Safe Array within a Safe Array Implementation

 
0
  #10
Jun 9th, 2008
> 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.
If at first you don't succeed, keep on sucking until you do succeed.
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:


Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC