2016-07-26 50 views
1

我写C++代码:如何在函数正确执行后修复Core Dumped错误?

#include <iostream> 
#include <queue> 
#include <stack> 
#include <vector> 
#include <unordered_map> 
#include <algorithm> 

using namespace std; 

template <class T> 
class TreeNode { 
public: 
    T data; 
    TreeNode<T> *left, *right; 

    TreeNode() { 
     data = {}; 
     left = right = NULL; 
    } 

    TreeNode(T data) { 
     this->data = data; 
    } 
}; 

template <class T> 
class BinaryTree { 
public: 
    TreeNode<T> *root; 

    vector<T> _largestIndependentSet(TreeNode<T> *root) { 
     static unordered_map< TreeNode<T>*, vector<T> > table; 

     if(!root) 
      return {}; 

     if(table.find(root) != table.end()) 
      return table[root]; 

     vector<T> lis = {}, lis_left = {}, lis_right = {}, 
      lis_nrl_left = {}, lis_nrl_right = {}, lis_nrr_left = {}, lis_nrr_right = {}; 

     // Leaf 
     if(!root->left && !root->right) { 
      lis.push_back(root->data); 
     }else{ 
      if(root->left){ 
       lis_left = _largestIndependentSet(root->left); 
       lis_nrl_left = _largestIndependentSet(root->left->left); 
       lis_nrl_right = _largestIndependentSet(root->left->right); 
      } 

      if(root->right){ 
       lis_right = _largestIndependentSet(root->right); 
       lis_nrr_left = _largestIndependentSet(root->right->left); 
       lis_nrr_right = _largestIndependentSet(root->right->right); 
      } 
      if( lis_left.size() + lis_right.size() > 
        lis_nrl_left.size() + lis_nrl_right.size() + 
        lis_nrr_left.size() + lis_nrr_right.size() + 1  ){ // don't keep root 
       lis.insert(lis.end(), lis_left.begin(), lis_left.end()); 
       lis.insert(lis.end(), lis_right.begin(), lis_right.end()); 
      } 
      else { 
       lis.insert(lis.end(), lis_nrl_left.begin(), lis_nrl_left.end()); 
       lis.insert(lis.end(), lis_nrl_right.begin(), lis_nrl_right.end()); 
       lis.insert(lis.end(), lis_nrr_left.begin(), lis_nrr_left.end()); 
       lis.insert(lis.end(), lis_nrr_right.begin(), lis_nrr_right.end()); 
       lis.push_back(root->data); 
      } 
     } 
     cout<<"Calculated Results for: "<<root->data<<": "; 
     for_each(lis.begin(), lis.end(), [](T data) { 
      cout<<data<<" "; 
     }); 
     cout<<"\n"; 
     table[root] = lis; 
     return table[root]; 
    } 

    void largestIndependentSet() { 
     vector<T> lis = _largestIndependentSet(this->root); 
     for_each(lis.begin(), lis.end(), [](T data) { 
      cout<<data<<" "; 
     }); 
    } 
}; 

int main() { 

    BinaryTree<int> bt; 
    TreeNode<int> *root = new TreeNode<int>(10); 
    root->left = new TreeNode<int>(7); 
    root->right = new TreeNode<int>(15); 
    root->left->left = new TreeNode<int>(9); 
    root->left->right = new TreeNode<int>(12); 
    root->right->left = new TreeNode<int>(6); 
    root->right->right = new TreeNode<int>(11); 
    root->left->left->left = new TreeNode<int>(20); 
    root->right->left->right = new TreeNode<int>(5); 
    root->left->left->left->left = new TreeNode<int>(22); 
    root->left->left->left->right = new TreeNode<int>(21); 
    root->right->left->right->left = new TreeNode<int>(4); 
    root->right->left->right->right = new TreeNode<int>(3); 
    bt.root = root; 

    bt.largestIndependentSet(); 
    return 0; 
} 

我它Cygwin使用g++ 5.4.0编译:

g++ binary_tree.cpp -std=c++11 

的问题是递归函数_largestIndependentSet()完成后,最后打印给我正确的答案。但之后,我得到这个错误:中止(核心转储),并在largestIndependentSet()打印不执行。

这是莫名其妙的,因为我的逻辑似乎是正确的。这是什么造成的?

PS:如果我有c++14标志编译运行良好O_O:

g++ binary_tree.cpp -std=c++14 
+2

您需要展示如何创建添加到地图的指针。'vector v = foo(some_apple);'没有足够的信息。如果你正在存储指向本地/临时对象的指针,那么这些指针在某个时刻将会失效。 – NathanOliver

+1

您是否尝试用调试器逐步执行代码? –

+0

@NathanOliver指针已经存在(这是一个自定义二叉树)。该地图用于存储附加信息以及矢量。我确信载体不会超出范围。 – prakharsingh95

回答

2

不进入在发布代码多于两个主要问题。

  • T -value构造函数的不确定子指针值。
  • largestIndependentSet()

前者的这些缺失的返回值是常见的,特别是对于C++初学者。确保你离开没有任何与不确定的价值。在这种情况下,TreeNode(T value)构造函数中的leftright不确定。

后者是非常重要的。函数largestIndependentSet()声称它正在返回一个向量,但实际上根本没有return。同样,调用未定义的行为。从那里我可以推测,但请注意这就是:猜测:

推测:编译器很高兴地生成了代码,最终将处理激活堆栈上发生的任何事情作为std::vector<T>进行处理。当然,这是不确定的胡言乱语,因为你从未返回过实际的物体。但是调用std::vector<>的非虚拟析构函数肯定不知道,并且在这样做时,将发生的任何事情都视为占据它认为是它的成员变量的有效数据,而事实上它只是一种有效数据。它的缺点是:取随机存储器,指向它的破坏程序代码,骗人的代码,并说内存中有一个有效的std::vector<>对象,然后松散析构函数。

至于为什么编译器没有错误。那么,通常在C或C++中,做一些不明智的事情并不是一个错误。编译器期望你足够了解你在做什么,在这种情况下,不存在语言违规,所以它给你带来了疑问。然而......在大多数现代编译器(icc,gcc,clang和msvc)中,将编译器警告级别调高到迂腐高度,会提醒您关于缺少返回值的。这些警告是有原因的,我强烈支持将它们视为错误(也是编译器选项),将它们视为错误

+0

我实际上已经将所有指针初始化为NULL,但后来我添加了第二个构造函数,忘记复制该行。一直在做C++足够长的时间才能知道这一点! – prakharsingh95

+0

@ prakharsingh95使用成员列表初始化。这是一个好习惯,对于复杂对象通常是首选的,因为它避免了不必要的默认初始化,所以TreeNode(T const&value):data(value),left(),right(){} – WhozCraig

相关问题