Кто-нибудь может объяснить, почему push_back() вызывает здесь SEGFAULT?

Я получаю segfault, и я сузил область возникновения проблемы, упростив мою функцию main() и используя 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();
    }
}

вывод программы при использовании 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

Похоже, SEGFAULT возникает, когда я пытаюсь скопировать объект Graph после того, как его размер увеличился (его матрица по умолчанию — 2x2). Я не знаю, ПОЧЕМУ это проблема, я просто знаю, что это происходит, когда matrix[n1][n2]->v.push_back(value) достигается в insert()

Класс графика (упрощенный):

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;
        }
}

Поле v моей структуры Edge неправильно перераспределяется, когда я каким-то образом изменяю размер матрицы? Я попытался посмотреть на этот ответ, но в моем случае v - это просто вектор, поэтому я не знаю, почему это применимо для меня.


person Nick Nagy    schedule 15.11.2019    source источник
comment
И когда вы использовали отладчик для запуска программы построчно, проверяя значения всех переменных, какие наблюдения вы сделали? Вы умеете пользоваться отладчиком? Если нет, то сейчас у вас есть отличная возможность научиться им пользоваться. Знание того, как использовать отладчик, является обязательным навыком для каждого разработчика C++. Ваш отладчик легко покажет, что некоторые из ваших переменных и членов класса не содержат того, что, по вашему мнению, они должны содержать, и, если в этот момент вы не понимаете почему, вы можете спросить об этом, что< /i>, но ответ на ваш вопрос прост: используйте отладчик.   -  person Sam Varshavchik    schedule 16.11.2019
comment
Что такое класс Circuit? Кроме того, абсолютно то, что сказал @SamVarshavchik. Я бы рекомендовал компилировать с -g для лучшей отладочной информации.   -  person n314159    schedule 16.11.2019
comment
Скорее всего, вы получите лучший ответ, если создадите stackoverflow.com/help/minimal-reproducible-example.   -  person Employed Russian    schedule 16.11.2019