0

I am currently creating a Quadtree, and I have found while debugging, that a method in my class is not changing the value of a particular integer.

Here is my code:

Quadrant.h

#ifndef QUADRANT_H
#define QUADRANT_H
#include "Point.h"
#include "Boundary.h"
#include <iostream>
struct Quadrant : Boundary
{
    Quadrant(const Boundary& AABB);
    void subdivide(std::vector<Quadrant>& m_quadrantStorage); //splits the quadrant into four children.
    bool insert(Point* pointnode, std::vector<Quadrant>& m_quadrantStorage);
    std::vector<Point*> fetchPoints();

    int firstChildindex; //stores the index of its first child. since the children are contiguous in the base array, you can find them by firstchild + i while 0<=i<4
    Point* firstpointnode = nullptr; //stores the beginning of a point list which are all in this current quadrant.
    int count = 0; 
    bool subdivided = false;


};  
#endif

Quadrant.cpp

#include "Quadrant.h"
#include "Globals.h"
#include <iostream>
Quadrant::Quadrant(const Boundary& AABB)
    :Boundary(AABB)
{

}
bool Quadrant::insert(Point* pointnode, std::vector<Quadrant>& m_quadrantStorage)
{
    if (!this->contains(pointnode->position)) return false; //if the point isnt within this boundary, forget about it.
    else if (count < QCAPACITY && !subdivided){ //otherwise if it is contained, and it isnt full, we can insert to the end of the point list.
        if (firstpointnode == nullptr) {
            firstpointnode = pointnode;
            firstpointnode->next = nullptr;
        }
        else {
            Point* currentpointnode = firstpointnode;
            while (currentpointnode->next != nullptr) //traversing to the end of this quadrant point list
            {
                currentpointnode = currentpointnode->next;
            }
            currentpointnode->next = pointnode; // currentpointnode is the last node in the list by this point.
            currentpointnode->next->next = nullptr; //disassociating any ties that the point had with any other points, so it is the absolute end of the list.
        }
        count++;
        return true;
    }
    else{
        if(!subdivided){//or if the point is within the quadrant, is full, and it hasnt already subdivided, subdivide.
            subdivided = true;
            count = 0;
            subdivide(m_quadrantStorage);
            firstpointnode = nullptr;
        }
        for (int i = 0; i < 4; i++) {
            if (m_quadrantStorage[firstChildindex + i].insert(pointnode, m_quadrantStorage)) return true;
            //std::cout << i << std::endl;
        }
    }

    return false;

}
void Quadrant::subdivide(std::vector<Quadrant>& m_quadrantStorage)
{
    sf::Vector2f newhalfsize = halfsize / float(2);
    firstChildindex = m_quadrantStorage.size();//children are contiguous in memory - nth child = firstChildindex + n for 0<=n<4
    m_quadrantStorage.emplace_back(Boundary{ sf::Vector2f { centre.x + newhalfsize.x, centre.y - newhalfsize.y }, newhalfsize });
    m_quadrantStorage.emplace_back(Boundary{ sf::Vector2f { centre.x + newhalfsize.x, centre.y + newhalfsize.y }, newhalfsize });
    m_quadrantStorage.emplace_back(Boundary{ sf::Vector2f { centre.x - newhalfsize.x, centre.y + newhalfsize.y }, newhalfsize });
    m_quadrantStorage.emplace_back(Boundary{ sf::Vector2f { centre.x - newhalfsize.x, centre.y - newhalfsize.y }, newhalfsize });
    Point* currentpointnode = firstpointnode;
    while (currentpointnode!= nullptr) //transferring all points from parent list to children.
    {
        for (int i = 0; i < 4; i++)
        {
            m_quadrantStorage[firstChildindex + i].insert(currentpointnode, m_quadrantStorage);
        }
        currentpointnode = currentpointnode->next;
    }
    firstpointnode = nullptr; // this parent does not have a point anymore, so it is nullptr.
    subdivided = true;
}
std::vector<Point*> Quadrant::fetchPoints()
{
    std::vector<Point*> vec;
    if (firstpointnode == nullptr) return vec;
    Point* currentNode = firstpointnode;
    while (currentNode->next != nullptr)
    {
        vec.emplace_back(currentNode);
        currentNode = currentNode->next;
    }
    return vec;
}

In the Visual Studio Watch, I see that the void Quadrant::subdivide(std::vector<Quadrant>& m_quadrantStorage) instantaneously changes the value of firstChildindex to 1, as intended, but after the line is executed, it changes to a random garbage value, then back to 0.

I really do not understand why this is happening.

Subdivide function called. The line which changes the value of firstChildindex has just executed, and now the value of firstChildindex is 1 as intended. Now, the value of firstChildindex is -572662307 And now firstChildindex has a value of 0!!

Ayxan Haqverdili
  • 23,309
  • 5
  • 37
  • 74
expl0it3r
  • 323
  • 1
  • 7
  • 2
    Please provide a [mre] instead of the whole project. – Ayxan Haqverdili Apr 20 '20 at 20:09
  • yes sure, very readable, maintainable and testable code... – Alberto Sinigaglia Apr 20 '20 at 20:11
  • Sounds like you've got [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior) somewhere in your program. But Visual Studio has arguably the best debugging capability, so you're in luck. Just put a write data breakpoint on that variable to quickly pinpoint who is overwriting it. – rustyx Apr 20 '20 at 20:18
  • But the thing is, it works fine in release mode but not in debug mode?? – expl0it3r Apr 20 '20 at 20:47
  • The debug heap will fill memory with different known values to represent unallocated/allocated/freed states as well as uses stack guards and such to enable you to find issues you might not always see in a release build. I'd say it's working. :) This table may help you decode them. https://stackoverflow.com/a/127404/920069 Looks like you may be accessing some freed memory. Reducing your code to a [mcve] would help others debug it with you instead of guessing. Often you'll find the problem yourself as you reduce. – Retired Ninja Apr 20 '20 at 21:42
  • I dont see where your firstChildindex variable is defined in your code. Depending on that, this sounds like a variable scope problem to me. – Tuncay Göncüoğlu Apr 21 '20 at 14:17
  • It is defined in quadrant.h, look in the first block of code – expl0it3r Apr 21 '20 at 17:23

0 Answers0