Encounter "Thread 1: EXC_BAD_ACCESS" when reading data from a txt. file

I am writing a program to print the input data in the format of (row, column, value). The first line in the input file tells the program the matrix dimension.

It seems to me that the program successfully read the first line since, in the debug area, rows, cols, and value are now filled with values correctly. For the rest, Xcode shows an error message saying **"Thread 1: EXC_BAD_ACCESS(code = 1, address = 0x0)**," and **(lldb)** shows up in my console.

Is this what causes:
smArray = (MatrixTerm*)NULL

in the debug area? I am not sure what's missing here. Can anyone help?

I tried add a declaration like:
1
2
  // declaration 
SparseMatrix(int r, int c, int t = 0); 

or edit the constructor like
1
2
3
 // constructor 
SparseMatrix::SparseMatrix(int r = 0, int c = 0, int t = 0):rows(r), cols(c), terms(t)
{ if(terms) smArray = new MatrixTerm[terms]; };


Either way, I encountered different errors, which made me even more confusing. Hope someone can kindly explain it to me.


The txt file looks like this:

4 5 6 // the number of rows, columns, and nonzero values
0 0 2
1 0 4
1 3 3
3 0 8
3 3 1
4 2 6



Main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    #include "SparseMatrix.h"
    #include <iostream>
    #include <fstream>
    
    int main() {
        
        SparseMatrix m(0,0,0);
        
        ifstream fin;
        fin.open ("sparse2.txt");
    
        // check fin and print error message
        if (!fin){
            cout << "Failed to open the file: " << "sparse2.txt" << "." << endl;
        }
        
        // input from a txt.file
        // print in the format of (ROW, COL, VALUE)
        else {
            fin >> m;
            cout << "ORIGINAL SPARCE MATRIX" << endl << m ;
        }
        
        fin.close();

        return 0;
    }


SparceMatrix.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
   
//-------------------- Sparse Matrix --------------------//
    
    // constructor
    SparseMatrix::SparseMatrix(int r, int c, int t):rows(r), cols(c), terms(t){
        if(terms) smArray = new MatrixTerm[terms];
    };
    
    // deconstructor
    SparseMatrix::~SparseMatrix(){
        delete []smArray;
    }
    
    // the copy constructor
    SparseMatrix::SparseMatrix(SparseMatrix&b){
        rows = b.rows;
        cols = b.cols;
        terms = b.terms;
        smArray = new MatrixTerm[terms];
        memcpy( smArray, b.smArray, terms*sizeof(MatrixTerm)); // memcpy: copy block of memory
    }

    //-------------------- istream/ostream --------------------//
    istream & operator>>(istream & is, SparseMatrix& m){
        is >> m.rows >> m.cols >> m.terms;
        int i;
        for (i = 0; i < m.terms; i++){
            is >> m.smArray[i].ROW >> m.smArray[i].COL >> m.smArray[i].VALUE;
        }
        return is;
    }
    
    // output in the format of (ROW, COL, VALUE)
    ostream & operator<<(ostream & os, SparseMatrix& m){
        int i;
        for (i = 0; i < m.terms; i++){
            os << "(" << m.smArray[i].ROW << "," << m.smArray[i].COL << "," << m.smArray[i].VALUE << ")" << endl;
        }
        os << endl << endl;
        return os;
    }

Last edited on
The operator>>() overload on line 24 overwrites the value of m.terms without updating the internal array, so if at the start of the function m.terms has a smaller value (say, zero), a buffer overflow will occur on line 28 when data is written past the end of m.smArray.

Another problem is with the way the constructor for SparseMatrix is written. If a zero is passed as the terms parameter, SparseMatrix::smArray is not initialized at all. When this object is destructed, an uninitialized pointer will be attempted to be deleted, causing undefined behavior.
@helios

Thank you for your quick response.

I am a C++ beginner, and I am not quite sure what to do, especially the operator part.

Now I set the constructor default in my SparceMatrix.h, is it the right thing to do? But I still cannot get rid of the error: Thread 1: EXC_BAD_ACCESS(code = 1, address = 0x0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class SparseMatrix; // forward declaration
class MatrixTerm; // forward declaration

/* ---------- Class MatrixTerm ---------- */

class MatrixTerm{
    
    friend istream & operator>>(istream & is, SparseMatrix& m);
    friend ostream & operator<<(ostream & os, SparseMatrix& m);
    
    friend class SparseMatrix;
    
private:
    int ROW, COL, VALUE;
};


/* ---------- Class SparceMatrix ---------- */

class SparseMatrix{
    
    friend istream & operator>>(istream & is, SparseMatrix & m);
    friend ostream & operator<<(ostream & os, SparseMatrix & m);

public:
    //---------- Sparse Matrix ----------//
    SparseMatrix();
    
    SparseMatrix(int r = 0, int c = 0, int t = 0);
    // The constructor function creates a SparseMatrix with:
    // r rows
    // c columns
    // t nonzero terms
    
    ~SparseMatrix();
    // The deconstructor
    
    SparseMatrix(SparseMatrix &);

private:
    int rows, cols, terms;
    // rows: the number of rows in the matrix
    // cols: the number of columns in the matrix
    // terms: the number of terms in the matrix
    
    MatrixTerm *smArray;
};

#endif /* SparseMatrix_h */ 
Topic archived. No new replies allowed.