Nano Hash - криптовалюты, майнинг, программирование

Как удалить узел октодерева С++ (узел был 0x4.)

У меня есть Octree, и мне нужно удалить узел, который ищет его ветвь. Программа может найти узел, но мне трудно его удалить. Когда я создаю объект своего Octree и создаю несколько узлов, но не удаляю их, деструктор удаляет Octree:

Octree::~Octree()
{
clear(root);
}

void Octree::clear(node *node){
for (int i = 0; i < 8; i++)
    if (node->child[i])
        clear(node->child[i]);

delete node;
}

Но когда я хочу удалить конкретный узел с помощью этого метода,

void Octree::deletebranch(int branch) {
node *n = search(branch);
if (n) {
    for (int i = 0; i < 8; i++) {
        if (n->child[i]) {
            delete n->child[i];
            n->child[i] = NULL;
        }
    }
    delete n;
    n = NULL;
}
else {
    printf("There is nothing to delete here");
}
}

Я получил исключение после вызова деструктора. Возникло исключение: нарушение доступа для чтения. узел был 0x4.

Я отлаживал шаг за шагом и обнаружил некоторые странные вещи. Когда я создаю узел, я делаю это так:

        n = new node;
        n->value = xvalue;
        for (int i = 0; i < 8; i++)
            n->child[i] = NULL;

И все в порядке, я установил значение, и значение узла равно xvalue, а дочерние элементы равны NULL. Но после того, как я удалил этот узел с помощью метода deletebranch(), мой узел изменился вот так.

  • п 0x00500788 {значение=0 дочерний=0x0050078c {0x00000004 {значение=??? child=0x00000008 {???, ???, ???, ???, ???, ...} }, ...} } Octree::node * значение 0 int
  • ребенок 0x0050078c {0x00000004 {значение=??? child=0x00000008 {???, ???, ???, ???, ???, ???, ???, ???} }, 0xfdfdfdfd {...}, ...} Octree ::узел *[8]
  • [0] 0x00000004 {значение=??? child=0x00000008 {???, ???, ???, ???, ???, ???, ???, ???} } Octree::node *
  • [1] 0xfdfdfdfd {значение=??? child=0xfdfdfe01 {???, ???, ???, ???, ???, ???, ???, ???} } Octree::node *
  • [2] 0xdddddddd {значение=??? child=0xddddddde1 {???, ???, ???, ???, ???, ???, ???, ???} } Octree::node *
  • [3] 0x29122f71 {значение=??? child=0x29122f75 {???, ???, ???, ???, ???, ???, ???, ???} } Octree::node *
  • [4] 0x0000a9bd {значение=??? child=0x0000a9c1 {???, ???, ???, ???, ???, ???, ???, ???} } Octree::node *
  • [5] 0x004d5228 {value=5249384 child=0x004d522c {0x005007a0 {value=5067304 child=0x005007a4 {0x004fe218 {...}, ...} }, ...} } Octree::node *
  • [6] 0x004fe218 {value=5244832 child=0x004fe21c {0x004d00c4 {value=5235224 child=0x004d00c8 {0x00501968 {...}, ...} }, ...} } Octree::node *
  • [7] 0xdddddddd {значение=??? child=0xddddddde1 {???, ???, ???, ???, ???, ???, ???, ???} } Octree::node *
  • this 0x0043f818 {root=0x005006b0 {value=0 child=0x005006b4 {0x00000000, 0x00000000, 0x00000000, ...} } } Octree *

Я действительно не понимаю, почему это так, потому что я никогда не менял узел после того, как удалил его. И я думаю, именно поэтому я получил это исключение в деструкторе. Как мне удалить узел? Может попробовать поймать?

Вот заголовочный файл:

class Octree
{ 
public:
struct node
{
    int value;
    node *child[8];
};

Octree();
~Octree();

void clear(node* node);
int convert(int sorszam);
node* searchandset(int dec, int value);
node *search(int dec);
node* step(node *node, int k);
void Print(node *n)const;
void put(int branch, int value);
void deletebranch(int branch);
node *root;
};
16.05.2016

  • Непонятно: Но после того, как я удалил этот узел с помощью метода deletebranch(), мой узел изменился. Вы смотрите на узел после его удаления. Если да, то это УБ. 16.05.2016
  • Я не знаю, что такое UB, но да, я просматриваю каждый узел, когда работает деструктор, и узел, который я удалил, имеет дочерние элементы и значение. Я скопировал узел после того, как он был удален выше. 16.05.2016
  • Для этого нужен минимальный воспроизводимый пример. Например. какой тип child? Как выглядит node? И т.д. и т.п. 16.05.2016
  • @T.dog UB — это сокращение от неопределенное поведение. Читайте также по внешним ссылкам на этой странице. UB то, с чем вы должны быть знакомы, если собираетесь программировать на C++. 16.05.2016
  • Что касается кода, который ищет узел и сохраняет его как n последующий delete n; n = NULL; - я надеюсь, вы понимаете, что последнее присвоение NULL ничего не сделало откуда бы n ни пришло. т.е. где-то там теперь сидит не-NULL-но-висящий указатель, находящийся в массиве child[]. Когда деструктор содержащего его узла срабатывает, он перечисляет child[], находит этот указатель и вызывает в нем delete. Но вы уже удалили узел, поэтому ваша проблема и что вам нужно исправить. 16.05.2016
  • Но почему n = NULL; ничего не сделал? Когда я использую только delete n; без n = NULL;, я получаю такое же исключение. Но если я вас понимаю, у меня есть указатель, отличный от NULL, где-то в узле, который я уже удалил, и когда деструктор пытается его удалить, я получаю это исключение. Чего я не понимаю, так это того, что если я удалил этот узел, почему деструктор пытается удалить его снова? И как я должен установить 'n' в NULL, чтобы предотвратить эту не-NULL-но-висячую ситуацию? 16.05.2016
  • @WhozCraig, не могли бы вы быть немного более конкретным? 17.05.2016

Новые материалы

Кластеризация: более глубокий взгляд
Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

Частный метод Python: улучшение инкапсуляции и безопасности
Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

Как я автоматизирую тестирование с помощью Jest
Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..