2016-07-11 2 views
-1

BST의 루트 노드를 반환하려고합니다. 내 재귀 함수는 SPnodes (트리 노드 객체)의 컨테이너로 std::vector을 사용하여 하나의 호출이 반복되고 더 적은 수의 요소가있는 벡터가 다음 호출로 전달됩니다. 벡터의 크기가 1이되면 내 함수는 벡터 컨테이너 인 nodeList의 첫 번째 (그리고 유일한) 요소에서 복사 생성자를 호출하여 생성 된 새로운 SPnode을 반환합니다.새 메모리를 할당 한 후 분할 오류가 발생했습니다.

다음은 래퍼 함수를 ​​통해 전달 된 다음 원래 호출자에게 전달됩니다.

질문

내가 벡터 용기가 파괴되는 범위를 벗어나면, 그러나 나는 그래서이 문제의 원인이 될 수 있는지 이해하지 못하는 새로운 메모리를 할당하고 SPnodes을 복사하고있어 이해 . 그렇다면이 원인은 무엇입니까? 내 문제는 의심 스럽지만, 수많은 질문을 통해 답을 찾지 못하는 것 같습니다.

코드

SPnode 헤더 :

#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 파일 :

#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; 
} 

내 기능 :

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); 
} 

도움을 주시면 감사하겠습니다.

+6

디버거로 코드를 단계별로 실행할 때 무엇을 관찰 했습니까? –

+3

코드가 너무 많습니다. [MCVE]를 사용하여 먼저 디버그하십시오! –

답변

0

recListToTree은 함수의 끝에서 돌아 오지 않으므로 모든 경로에서 값을 반환하지 않습니다 (컴파일러에서 경고 수준을 올리면이 점을 알 수 있습니다). 이 가비지 반환 값이 충돌의 원인입니다.

은 충돌과 관련,하지만 메모리 누수 문제는 recConstructor가 지나치게 복잡하다 (모든 중복 IFS)과 재귀 호출 한 번 이상 new에 의해 호출 복사 생성자를 통해 한 번 (2 회 일을 복사 한 것입니다하지 않음 ~ recConstructor).

관련 문제