2016-07-26 44 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

相關問題