0

I've been getting a segfault and I narrowed down where the issue comes up by simplifying my main() function and using valgrind.

main.cpp

int main() {
    unique_ptr<Graph> g1 = make_unique<Graph>();
    unique_ptr<Graph> g2 = make_unique<Graph>();
    for (int i = 0; i < 10; i++) {
        g1->insert(1, 0+i, 1+i);
        cout << i << endl;
        g2 = g1->copy();
    }
}

output from program when using valgrind:

0
1
==10545== Invalid read of size 8
==10545==    at 0x110612: std::vector<unsigned int, std::allocator<unsigned int> >::push_back(unsigned int const&) (in /home/user/Program/C++/main)
==10545==    by 0x1176F9: Graph::insert(unsigned int, unsigned int, unsigned int) (in /home/user/Program/C++/main)
==10545==    by 0x117D5B: Graph::copy() (in /home/user/Program/C++/main)
==10545==    by 0x10D5DA: main (in /home/user/Program/C++/main)
==10545==  Address 0x10 is not stack'd, malloc'd or (recently) free'd

It looks like SEGFAULT occurs when I try to copy a Graph object after its size has increased (its default matrix is 2x2). I don't know WHY it's an issue, I just know it's happening when matrix[n1][n2]->v.push_back(value) is reached in insert()

Graph class (simplified):

class Graph {
    private:
        struct Edge {
            // fields... 
            vector<unsigned int> v;
            // functions...
        }

        unsigned int size = 2;

        vector<vector<shared_ptr<Edge>>> matrix = vector<vector<shared_ptr<Edge>>>(size,             
               vector<shared_ptr<Edge>>(size));

        void resize(unsigned int newSize) {
            matrix.resize(newSize);
            for (unsigned int i = 0; i < newSize; i++) {
                matrix[i].resize(newSize);
            }
            if (newSize > size) {
                for(unsigned int j = 0; j < newSize-1; j++) {
                    matrix[j][newSize-1] = make_shared<Edge>();
                    matrix[newSize-1][j] = matrix[j][newSize-1];
                }
                matrix[newSize-1][newSize-1] = matrix[0][0];
            }
            size = newSize;
        }

    public:
        Graph() { // matrix[i][j] = matrix[j][i], matrix[i][i] = invalid
            shared_ptr<Edge> E = make_shared<Edge>();
            shared_ptr<Edge> other = make_shared<Edge>(); // placeholder, not to be used
            matrix[0][0] = other;
            matrix[0][1] = E;
            matrix[1][0] = E;
            matrix[1][1] = other;
        }

        ~Graph() {
            vector<vector<shared_ptr<Edge>>>().swap(matrix);
        }

        char insert(unsigned int value, unsigned int n1, unsigned int n2) {
            if (n1==n2) return 0;
            if (n1 > n2) {
                int temp = n1;
                n1 = n2;
                n2 = temp;
            }
            if (value==0 || n2>size || (n2==size&&n1 < size-1)) return 0;
            if (n2 == size) {
                resize(size+1);
            }
            matrix[n1][n2]->v.push_back(value); // SEGFAULT HERE!!
            return 1;
        }

        // segfault seems to happen when resizing ? 
        unique_ptr<Graph> copy() {
            unique_ptr<Graph> thisCopy = make_unique<Circuit>();
            if(size!=2) thisCopy->resize(size);
            for (unsigned int i = 0; i < size-1; i++) {
                for (unsigned int j = 0; j < size; j++) {
                    if (i!=j) {
                        for (unsigned int n: matrix[i][j]->v) {
                            thisCopy->insert(n, i, j); // <--error happens here
                        }
                    }
                }
            }
            return thisCopy;
        }
}

Is the v field of my Edge struct getting improperly re-allocated when I resize the matrix in some fashion? I tried looking at this answer but in my case v is just an vector, so I don't know why that would apply for me.

Nick Nagy
  • 61
  • 4
  • And when you used your debugger to run your program one line at a time, while inspecting the values of all variables, what observations did you make? Do you know how to use a debugger? If not, now is an excellent opportunity for you to learn how to use one. Knowing how to use a debugger is a required skill for every C++ developer. Your debugger will easily show how some of your variables and class members don't contain what you think they should contain, and, if at that point you don't understand why, then you can ask about ***that***, but the answer to your question is simply: use a debugger. – Sam Varshavchik Nov 15 '19 at 23:36
  • What is the class `Circuit`? Also, absolutely what @SamVarshavchik said. I would recommend compiling with `-g` for better debug information. – n314159 Nov 15 '19 at 23:37
  • You will likely get a better answer if you create https://stackoverflow.com/help/minimal-reproducible-example – Employed Russian Nov 16 '19 at 19:32

0 Answers0