0

Here is my Quadrant Class:

#ifndef QUADRANT_H
#define QUADRANT_H

#include "Point.h"
#include "Boundary.h"

struct Quadrant : Boundary
{
    Quadrant* firstchild = nullptr;
    Point* firstPoint = nullptr;
    int count = -1;
    bool subdivided;
    Quadrant(const Boundary& AABB);
    void subdivide(std::vector<Quadrant>& m_quadrantStorage);
};  

#endif

Here is my Quadrant class CPP:

#include "Quadrant.h"

#include <iostream>
Quadrant::Quadrant(const Boundary& AABB)
    :Boundary(AABB), subdivided(false)
{

}

void Quadrant::subdivide(std::vector<Quadrant>& m_quadrantStorage)
{
    sf::Vector2f newhalfsize = halfsize / float(2);
    Boundary NEB{ sf::Vector2f { centre.x + newhalfsize.x, centre.y - newhalfsize.y }, newhalfsize };
    Boundary SEB{ sf::Vector2f { centre.x + newhalfsize.x, centre.y + newhalfsize.y }, newhalfsize };
    Boundary SWB{ sf::Vector2f { centre.x - newhalfsize.x, centre.y + newhalfsize.y }, newhalfsize };
    Boundary NWB{ sf::Vector2f { centre.x - newhalfsize.x, centre.y - newhalfsize.y }, newhalfsize };
    //SIZE OF m_quadrantStorage is 1 AT THIS LINE.
    m_quadrantStorage.emplace_back(NEB); //SIZE OF m_quadrantStorage is 2 AT THIS LINE.
    firstchild = &m_quadrantStorage.at(1);
    m_quadrantStorage.emplace_back(SWB);
    m_quadrantStorage.emplace_back(SEB);
    m_quadrantStorage.emplace_back(NWB);

    //First child is a pointer to the second element in m_quadrantStorage
    std::cout << "FIRST CHILD ADDRESS:" << firstchild << std::endl;
    std::cout << &m_quadrantStorage[1] << std::endl;
}

Here is my Quadtree class header:

#ifndef QUADTREE_H
#define QUADTREE_H

#include "Quadrant.h"
#include "Point.h"
#include <vector>

class Quadtree
{
public:
    Quadtree(sf::RenderWindow* winptr);
    void display() const;
    void debug();
    std::vector<Quadrant> m_quadrantStorage;
private:
    sf::RenderWindow* m_winPtr = nullptr;
    std::vector<Quadrant*> findleaves(const Boundary& rect);
    bool insert(Point* point);
};

#endif

Here is my Quadtree class cpp:

#include "Quadtree.h"
#include "Globals.h"
#include <iostream>
Quadtree::Quadtree(sf::RenderWindow* winptr)
    :m_winPtr(winptr)
{   m_quadrantStorage.emplace_back(Boundary{ sf::Vector2f{0.0f,0.0f}, sf::Vector2f{WIDTH / 2,HEIGHT / 2} });
}

void Quadtree::display() const
{
    for (const auto& q : m_quadrantStorage)
    {
        m_winPtr->draw(q);
    }
}

std::vector<Quadrant*> Quadtree::findleaves(const Boundary& rect)
{
    std::vector<Quadrant*> leaves;
    std::vector<Quadrant*> to_process;
    to_process.push_back(&m_quadrantStorage[0]);
    while (to_process.size() > 0)
    {
        Quadrant* node = to_process[to_process.size() - 1];
        to_process.pop_back();

        if (node->count != -1)
        {
            leaves.push_back(node);
        }
        else
        {
            for (int i = 0; i < 4; i++)
            {
                if (rect.intersects<Quadrant>(*(node + i)))
                {
                    to_process.push_back(node + i);
                }
            }
        }
    }
    return leaves;
}

void Quadtree::debug()
{
    m_quadrantStorage[0].subdivide(m_quadrantStorage);
    //std::cout << "{" << (m_quadrantStorage[0].firstchild)->centre.x << "," << (m_quadrantStorage[0].firstchild)->centre.y << "}" << std::endl;
    //std::vector<Quadrant*> quadz = findleaves(Boundary{ sf::Vector2f{0,0}, sf::Vector2f{WIDTH / 2,HEIGHT / 2} });
    //std::cout << quadz.size() << std::endl;
}

Ok, I have seen from the comments that DDDDDD is indicative of freed heap in debug mode. But I have switched to release and the memory locations are not the same.

image

After pushing a quadrant object to an external vector which was taken by reference, and saving the memory location of the newly pushed object in a variable, the memory location of the actual object in the vector, and the one in the pointer are not the same.

image

I get the pointer's memory address to be DDDDDDD and the memory address of the object to be valid. I dont understand what is going on.

image

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
expl0it3r
  • 325
  • 1
  • 7
  • Where is your code? – Michael Chourdakis Apr 19 '20 at 22:59
  • This will tell you what 0xdddddddd means: [https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations](https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations) – drescherjm Apr 19 '20 at 22:59
  • I have switched to release mode and they still do not have the same memory locations. – expl0it3r Apr 19 '20 at 23:01
  • How should I fix this? – expl0it3r Apr 19 '20 at 23:03
  • What is `firstchild`? `firstchild = &m_quadrantStorage.at(1);` looks suspicious to me, possible undefined behavior if the vector size changes at all. – drescherjm Apr 19 '20 at 23:04
  • `std::vector` moves its elements when it grows. – Miles Budnek Apr 19 '20 at 23:04
  • m_quadrantStorage stores Quadrants contiguously. When A quadrant subdivides through the subdivide function creates four children, which are pushed to m_quadrantStorage. Since they are contiguous, I thought I didn't have to store an array of the children, but instead, take the memory location of the first child, and iterate up to four to get each child. – expl0it3r Apr 19 '20 at 23:11
  • I think making a [mcve] would help. – Ted Lyngmo Apr 19 '20 at 23:11
  • I see... I have done a little test to check the memory location of the first element before and after pushing some objects into the vector, and I can see that the memory address changes. – expl0it3r Apr 19 '20 at 23:15
  • By making a [mcve] everyone interested can throw analysis tools at the problem. Also, replace the links to pictures with putting the actual output in the question as text. – Ted Lyngmo Apr 19 '20 at 23:23
  • Guys so all the vector member memory locations change when pushing back. I am not too sure of a solution. – expl0it3r Apr 19 '20 at 23:26
  • 1
    @jasbindra00 They may do, yes. If the vector needs to reallocate, everything will move. If you know how many elements you'll put in the vector (before starting to put the elements in), use `reserve()`. If you don't know but don't need the elements to be consecutive in memory, you can also use a `std::list` - the `std::list` elements won't move around as you put more and more elements in. – Ted Lyngmo Apr 19 '20 at 23:30
  • I have decided to store the index of the first child instead of its exact memory location. That way, I can access their children just by index + i for i < 3, regardless of any vector reallocations. – expl0it3r Apr 19 '20 at 23:42
  • 1
    Thank you everyone for your feedback. – expl0it3r Apr 19 '20 at 23:50

0 Answers0