Удаление указателей через вектор указателей

Итак, я работаю над проблемой сетевого потока и должен иметь возможность удалить правую половину моего двудольного графа, чтобы иметь дело с несколькими графами одновременно. Вот как у меня настроены классы узлов и краев:

class Node {
public:
    Node();
    int id;
    int visited;
    Node_Type type;
    vector <bool> letters;
    vector <class Edge *> adj; // Adjacency list
    class Edge *backedge;
};

class Edge {
public:
    Node *to;
    Node *from;
    Edge *reverse; // Edge with opposite to/from
    int original; // 1 on normal
    int residual; // 0 on normal
};

И потенциальный график можно увидеть на этом изображении:

Изображение графика

Где моя цель - удалить все ребра и узлы справа от второго столбца.

У меня есть все мои узлы, организованные в векторе указателей узлов, проиндексированных слева направо/сверху вниз, и я пытаюсь пройти по этому вектору и удалить все ребра, содержащиеся в списке смежности узла, которые находятся во втором и третьем столбцах. или третий и четвертый столбцы. После чего я пройду назад и удалю узел стока, а также узлы третьего столбца, а затем, наконец, изменю размер вектора узлов, чтобы разместить только первые два столбца узлов.

Вот как я это делаю:

void DeleteHalfGraph() {
    int i, j;

    // Delete all edges between dice, words, and the sink
    for(i = 1; i < nodes.size(); i++) {
        if(nodes[i]->type == DICE) { // DICE refers to the second column of nodes
            for(j = 0; j < nodes[i]->adj.size(); j++) {
                if(nodes[i]->adj[j]->to->type == WORD) {
                // WORD refers to the third column of nodes
                    delete nodes[i]->adj[j];
                }
            }
        }
        else if(nodes[i]->type == WORD || nodes[i]->type == SINK) {
        // SINK refers to the 4th column of nodes
            for(j = 0; j < nodes[i]->adj.size(); j++) {
                delete nodes[i]->adj[j];
            }
        }
    }

    // Delete all nodes now not connected to edges
    // minNodes = 5, size of the vector without the 3rd/4th columns
    for(i = nodes.size() - 1; i >= minNodes; i--) {
        if(nodes[i]->backedge != NULL) delete nodes[i]->backedge;
        delete nodes[i];
    }

    nodes.resize(minNodes);
}

Ошибка, которую я получаю при компиляции:

*** Error in `./worddice': malloc(): memory corruption (fast): 0x0000000000c69af0 ***

Возможно, я просто неправильно понимаю свои указатели, поскольку в последнее время я не занимался освобождением памяти таким образом. В любом случае, где я ошибаюсь? Любая помощь приветствуется.


person Toy_Reid    schedule 13.04.2017    source источник
comment
Подобная ошибка часто означает, что в какой-то момент ранее в программе вы совершили какое-то неопределенное поведение, которое не было обнаружено до сих пор. Такой инструмент, как valgrind, может помочь выявить такие ошибки.   -  person aschepler    schedule 14.04.2017
comment
Я вижу много удалений, но ничего нового... опять же, я думаю, что было бессмысленно вставлять эту часть...   -  person Evan Carslake    schedule 14.04.2017
comment
@EvanCarslake Итак, это то, что я видел, когда пытался найти похожие проблемы. Я делаю все свои новые действия в main, а затем вызываю эту функцию, которая на самом деле является членом класса Graph (я удалил это для простоты в своем вопросе). Я планирую попытаться передать все новости в конструктор класса Graph, но я решил сначала попробовать это так. Должны ли они оба сообщения/удаления содержаться в одном классе? У меня сложилось впечатление, что вы можете удалить память из любого указателя, который на нее указывает.   -  person Toy_Reid    schedule 14.04.2017
comment
@Toy_Reid да, все, что вы обновили, вы можете удалить по указателю на него, где угодно, один раз.   -  person Evan Carslake    schedule 14.04.2017
comment
Возможно, вы дважды удаляете один и тот же указатель. Может быть, вам следует использовать умный указатель вместо обычных указателей?   -  person Barmar    schedule 14.04.2017
comment
@Barmar Профессор просит нас скомпилировать для C ++ 98, к сожалению, поэтому умные указатели не годятся. Я понятия не имею, как их использовать независимо.   -  person Toy_Reid    schedule 14.04.2017
comment
Добавьте счетчики ссылок к своим узлам.   -  person Barmar    schedule 14.04.2017
comment
@Barmar Разве это не C ++ 11 и выше?   -  person Toy_Reid    schedule 14.04.2017
comment
@Toy_Reid предлагает вам сделать свой собственный умный указатель бедняка: когда вы планируете deleteing узел, уменьшите и проверьте счетчик. Если ноль, перейдите к delete. Конечно, это означает, что вы должны увеличивать счетчик всякий раз, когда вы назначаете Node. Это прекрасная возможность попрактиковаться в RAII и < href="http://stackoverflow.com/questions/4172722/what-is-the-rule-of-three">Правило трех и оберните указатель Node в объект счетчика и обойдите встречный объект.   -  person user4581301    schedule 14.04.2017
comment
Привет, ребята (@Toy_Reid и @user4581301)! Я надеюсь, что не слишком быстро прошел мимо вопроса и, возможно, упустил суть. Но, возможно, путь с минимальными усилиями (учитывая С++ 98) может заключаться в установке переменных в NULL (= 0) после удаления и проверке того, не являются ли переменные NULL (! = 0) перед их удалением. Например: ‹code› #define NULL 0 if(nodes[i]-›adj[j]) { delete nodes[i]-›adj[j]; nodes[i]-›adj[j] = NULL ; } ‹/код›   -  person diogoslima    schedule 14.04.2017
comment
@diogoslima Это не помогает, потому что может быть несколько указателей на один и тот же узел. Установка одного указателя на NULL не влияет на другие указатели.   -  person Barmar    schedule 14.04.2017
comment
@diogoslima Вы можете безопасно delete NULL. Он проверяет для вас. Ваш подход работает для предотвращения некоторых двойных удалений, но все же оставляет минное поле других узлов, которые могут попытаться перейти к этому удаленному узлу, потому что они не были отцеплены и все еще ожидают, что он будет там. Вы не хотите delete узла, пока никто не связан с ним, с уважением к риску оставить цикл узлов, вырезанных из остальной части графа.   -  person user4581301    schedule 14.04.2017
comment
Спасибо, ребята, за все отзывы! По какой-то причине я не позволю мне упомянуть каждого из вас (я новичок в StackOverflow). Решение на самом деле оказалось довольно простым: я не менял размер своего списка смежности после удаления из него ребер, поэтому, когда я добавлял новые ребра к вектору для следующего графа, пустые указатели все еще оставались там. Удаление их из моего вектора смежности устранило проблему :)   -  person Toy_Reid    schedule 14.04.2017


Ответы (1)


Решение на самом деле оказалось довольно простым: я не менял размер своего списка смежности после удаления из него ребер, поэтому, когда я добавлял новые ребра к вектору для следующего графа, пустые указатели все еще оставались там ( к которому я пытался получить доступ в других частях моей программы). Удаление их из моего вектора смежности устранило проблему.

person Toy_Reid    schedule 14.04.2017