Проблема с утечкой памяти - PullRequest
1 голос
/ 05 ноября 2019

Я пытаюсь создать трассировщик пути, который может визуализировать сетки, но у меня есть проблема, пытаясь построить наивную иерархию ограничивающих томов, которая поможет мне пройти через сетку и повысить производительность. Однако я столкнулся с проблемой, когда всякий раз, когда я пытался рекурсивно разделить вершины в сетке (в конечном счете, создавая bvh, я думаю), это приводило к утечке памяти и связывалось с файлом cpp "new_scalar.cpp", сообщавшим мне о переполнении стека. .

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

#include <iostream>
#include <vector>
#include <ctime>

#define print(x) std::cout << x << std::endl;

struct Node {
    std::vector<float*> Numbers;

    Node* LeftNode;
    Node* RightNode;

    void Partition() {
        if (Numbers.size() > 4) {
            // Find center
            float min = HUGE_VALF;
            float max = -HUGE_VALF;

            for (int i = 0; i < Numbers.size(); i++) {
                min = fmin(min, *Numbers[i]);
                max = fmax(max, *Numbers[i]);
            }

            float center = (min + max) * 0.5f;

            // Partitioning
            LeftNode = new Node;
            RightNode = new Node;

            for (int i = 0; i < Numbers.size(); i++) {
                if (*Numbers[i] < center) {
                    LeftNode->Numbers.push_back(Numbers[i]);
                }
                else {
                    RightNode->Numbers.push_back(Numbers[i]);
                }
            }

            LeftNode->Partition();
            RightNode->Partition();
        }
    }
};

struct Object {
    Node* Root;

    void BuildBVH(std::vector<float*> numbers) {
        Root = new Node;
        Root->Numbers = numbers;
        Root->Partition();
    }
};

int main()
{
    srand(std::clock());


    // Initialize vector
    std::vector<float*> numbers;

    for (int i = 0; i < 100000; i++) {
        float* newNumber = new float;
        *newNumber = ((float)(rand() % 1000000) / 1000000.0f) * 2.0f - 1.0f;

        numbers.push_back(newNumber);
    }


    Object object;
    object.BuildBVH(numbers);
}

Ответы [ 2 ]

2 голосов
/ 05 ноября 2019

В вашей функции Partition вы рекурсивно вызываете Partition:

 LeftNode->Partition();
 RightNode->Partition();

Каждый раз, когда вы вызываете функцию в C ++, адрес возврата (и любые параметры) помещаются в стек. Размеры стека C ++ варьируются от нескольких килобайт до нескольких мегабайт, но на самом деле они не предназначены для глубокой рекурсии. Таким образом, вы не хотите рекурсивно вызывать Partition 100 000 раз. Может быть, что рефакторинг в петлю?

1 голос
/ 05 ноября 2019

Вы увеличиваете 100 000 поплавков до numbers, а затем вызываете Partition() на них. Partition() вызывает Partition() для обеих сторон, снова и снова (пока Numbers не станет меньше 4, что все еще занимает некоторое время). Вы просто переполняете свой стек вызовов, повторяя слишком много раз.

Примечание: прекратите использовать new, как это.

...