Ошибка сегментации при создании большого дерева в C

#c #memory #tree

#c #память #дерево

Вопрос:

Я сталкиваюсь с ошибкой сегментации при попытке создать слишком большое дерево. Если tree_size = 10000, программа работает нормально, но когда tree_size = 100000, программа завершает работу непосредственно перед последней строкой (т. е. после инструкции печати «Готово»).

Мне кажется, что tree_size, равный 100 000, не должен быть таким большим, поэтому я был бы удивлен, если бы на моем компьютере закончилась память или что-то в этом роде. Ошибка сегментации связана с кодом или моим компьютером?

Это код, который я использую:

 #include <iostream>
#include <memory>
#include <vector>

template<class T> using sp = std::shared_ptr<T>;
template<class T> using wp = std::weak_ptr<T>;

struct Node: public std::enable_shared_from_this<Node>
{
    std::string value;
    std::vector<sp<Node> > children;
    wp<Node> parent;

    Node(std::string value, const wp<Node>amp; parent = wp<Node>())
    : value {value}
    , children {std::vector<sp<Node>>()}
    , parent {wp<Node>()}{}

    sp<Node> AddLeaf(const std::stringamp; value)
    {
        sp<Node> newLeaf = std::make_shared<Node>(value, shared_from_this());
        this->children.emplace_back(std::move(newLeaf));
        return this->children.back();
    }
};

int main(int argc, char * argv[])
{
    int tree_size = 100000;
    sp<Node> root = std::make_shared<Node>(std::to_string(0));
    sp<Node> current = root;
    for(int i = 1; i < tree_size;   i)
    {
        current->AddLeaf(std::to_string(i));
        current = current->children[0];
    }
    std::cout << "Finished" << std::endl;
    return 0;
}
  

При отладке в XCode я получаю сообщение об ошибке «Поток 1: EXC_BAD_ACCESS [code=2, address=0x7fff5f3ffff8]».

Комментарии:

1. На первый взгляд, я предполагаю, что у вас заканчивается стек из-за слишком глубокой рекурсии. Корневой Node деструктор вызывает деструкторы каждого Node элемента children , которые, в свою очередь, вызывают деструкторы своих дочерних элементов и так далее.

2. Да, классическая проблема. Вам пришлось бы написать деструктор самостоятельно.

3. Создаваемое вами «дерево» на самом деле представляет собой односвязный список длиной в 100 000 элементов. Когда root выходит за пределы области видимости, это запускает рекурсию глубиной 100 000 уровней. Это не сработает — стек выполнения является ограниченным ресурсом.

4. Спасибо, есть идеи, как я могу обойти ограничение стека в подобных случаях?