Segmentation fault after allocating new memory

时间:2016-07-11 20:55:05

标签: c++ segmentation-fault

I am trying to return the root node of a BST. My recursive function involves using std::vector as a container for SPnodes (the tree node object) which during a single call is iterated over and a vector with fewer elements is passed up to the next call. Once the vector is of size 1, my function returns a new SPnode which is created by calling the copy constructor on the first (and only) element in nodeList, the vector container.

This is then passed through the wrapper function and then to the original caller.

Question

I understand that when the vector container goes out of scope it is destroyed, however I'm allocating new memory and copying the SPnodes so I don't understand how this could be causing the problem. So then, what is causing this? I doubt my problem is unique, but I can't seem to find an answer after going through countless SO questions.

Code

SPnode header:

#ifndef SPNODEOBJ_H
#define SPNODEOBJ_H

#include "IntervalObjects.h"
#include "IntervalObj.h"
#include "InVecObj.h"
#include "StandardLib.h"

// --- SPnode Class ------------------------------------------------------------

// SPnode (or Subpaving Node), is a node in a binary tree which contains a
// parameter "box" which is an InVec object, and a left and right child which
// are also SPnode objects. These SPnode objects are the resultant boxes from 
// calling the expand method on m_box. This implementation allows for two 
// important characteristics: there is a way to determine "where" a given box in
// a subpaving is by iterating over a node's left or right child, which in turn
// allows for greater efficiency; secondly, the tree structure gives a "history"
// of the subpaving, which allows for the determination of parent boxes.
class SPnode
{
private:

    InVec m_box;

    // left and right children of this SPnode object - note that these must be
    // pointers in order to use them in the definition of the class, otherwise 
    // SPnode would reference itself in its definition
    SPnode* m_left;
    SPnode* m_right;

    // a boolean sepcifying whether the SPnode m_box is in the given subpaving 
    bool m_inSP;

    bool m_hasBeenIterated;

public:

    SPnode(InVec box): m_box(box), m_left(NULL), m_right(NULL), m_inSP(true), 
    m_hasBeenIterated(false) {}

    SPnode(const SPnode &ASP)
    {
        recConstructor(this, ASP);
    }

    void recConstructor(SPnode* const &parent, const SPnode &ASP);
    void recDestructor(SPnode* const &ASP);

    ~SPnode() {delete m_left;
               delete m_right;}



    // getters and setters
    InVec getBox() const {return m_box;}
    SPnode* getLeft() const {return m_left;}
    SPnode* getRight() const {return m_right;}
    bool getInSP() const {return m_inSP;}
    bool getIterated() const {return m_hasBeenIterated;}

    void setBox(const InVec box) {m_box = box;}
    void setLeft(SPnode* const p_node) {m_left = p_node;}
    void setRight(SPnode* const p_node) {m_right = p_node;}
    void setInSP(bool truth) {m_inSP = truth;} // when this is called truth 
                                               // should only be false
    void setIterated(bool truth) {m_hasBeenIterated = truth;}

    bool isLeaf() const;



    friend std::ostream& operator<< (std::ostream &out, const SPnode &ASP);

    SPnode operator=(const SPnode& ASP)
    {
        std::cout << "assignment called\n";
        if (this == &ASP) return *this;

        recConstructor(this, ASP);

        return *this;
    }


    friend void expand(SPnode &ASP);
    friend InVec lower(const InVec &box, const Interval &width, int axis);
    friend InVec upper(const InVec &box, const Interval &width, int axis);
    friend void mince(SPnode &ASP); 
    friend SPnode regularize(ImList &list, InVec box);
    friend SPnode* recRegularize(std::vector<InVec> &list, SPnode &parentNode);
};

#endif

SPnode cpp file:

#include "SPnodeObj.h"

void SPnode::recConstructor(SPnode* const &parent, const SPnode &ASP)
{
    parent->m_box = ASP.m_box;
    parent->m_inSP = ASP.m_inSP;
    parent->m_hasBeenIterated = ASP.m_hasBeenIterated;

    if (ASP.isLeaf()) 
    {
        parent->m_left  = NULL;
        parent->m_right = NULL;
        return;
    }

    if (ASP.m_left == NULL)
    {
        parent->m_left = NULL;
    }

    if (ASP.m_right == NULL)
    {
        parent->m_right = NULL;
    }


    if (ASP.m_left != NULL)
    {
        parent->m_left = new SPnode((ASP.m_left)->m_box);       
    }

    if (ASP.m_right != NULL)
    {
        parent->m_right = new SPnode((ASP.m_right)->m_box);
    }


    if (ASP.m_left != NULL)
    {
        recConstructor(parent->m_left, *(ASP.m_left));
    }

    if (ASP.m_right != NULL)
    {
        recConstructor(parent->m_right, *(ASP.m_right));
    }

}



bool SPnode::isLeaf() const
{
    return (m_left == NULL && m_right == NULL);
}


std::ostream& operator<< (std::ostream &out, const SPnode &ASP)
{
    if (ASP.m_right == NULL && ASP.m_left != NULL)
    {
        out << "SPnode(SPnode, " << ASP.m_box << ", NULL)";
    }

    else if (ASP.m_left == NULL && ASP.m_right != NULL)
    {
        out << "SPnode(NULL, " << ASP.m_box << ", SPnode)";
    }

    else if (ASP.m_left == NULL && ASP.m_right == NULL)
    {
        out << "SPnode(NULL, " << ASP.m_box << ", NULL)";
    }

    else
    {
        out << "SPnode(SPnode, " << ASP.m_box << ", SPnode)";
    }

    return out;
}

and my functions:

SPnode* listToTree (std::vector<InVec> boxList)
{
    int counter = 0;
    std::vector<SPnode> nodeList;

    for (auto box : boxList)
    {   
        nodeList.push_back(SPnode(box));
        counter += 1;
    }

    //return recListToTree(nodeList);
    //return new SPnode(*(recListToTree(nodeList)));

    return recListToTree(nodeList);
}


SPnode* recListToTree (std::vector<SPnode> &nodeList)
{

    std::cout << "nodelist size is: " << nodeList.size() << "\n";

    if (nodeList.size() == 1)
    {
        return new SPnode(nodeList.at(0));
    }


    std::vector<SPnode> parentNodeList;

    int counter = 0;

    for (auto node : nodeList)
    {

        if (node.getIterated())
        {
            counter += 1;
            continue;
        }

        if (counter + 1 == nodeList.size())
        {
            parentNodeList.push_back(SPnode(node.getBox()));
            break;
        }

        if (node.getBox().isAdjacent(nodeList.at(counter + 1).getBox()))
        {

            SPnode newNode =
            SPnode(node.getBox().combine(nodeList.at(counter + 1).getBox()));



            if (lessThan(node.getBox(), nodeList.at(counter + 1).getBox()))
            {
                newNode.setLeft (new SPnode(node));
                newNode.setRight(new SPnode((nodeList.at(counter + 1))));
            }

            else
            {
                newNode.setRight(new SPnode(node));
                newNode.setLeft (new SPnode((nodeList.at(counter + 1))));
            } 

            parentNodeList.push_back(SPnode(newNode));



            nodeList.at(counter).setIterated(true);
            nodeList.at(counter + 1).setIterated(true);

            counter += 1;
        }


        else
        {
            parentNodeList.push_back(SPnode(node.getBox()));

            nodeList.at(counter + 1).setIterated(true);

            counter += 1;
        }
    }

    recListToTree(parentNodeList);
}

Any help is appreciated!

1 个答案:

答案 0 :(得分:0)

recListToTree不会在所有路径上返回值,因为函数末尾没有返回值(在编译器中调高警告级别以告诉您这一点)。此垃圾返回值可能是导致崩溃的原因。

与崩溃无关,但内存泄漏问题是,recConstructor过于复杂(所有重复的ifs)并且会复制两次(一次通过new调用的复制构造函数,然后再通过递归调用recConstructor)。