如何在函数正确执行后修复Core Dumped错误?

时间:2016-07-26 14:54:36

标签: c++ c++11 memory-leaks stl core

我写了C ++代码:

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

我使用g++ 5.4.0上的Cygwin编译了它:

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

问题是递归函数_largestIndependentSet()完成后,最后一次打印给出了正确的答案。但在此之后我收到此错误:已中止(核心转储),并且largestIndependentSet()中的打印无法执行。

这令人困惑,因为我的逻辑似乎是正确的。造成这种情况的原因是什么?

PS:如果我用c++14标志编译它,它运行正常o_O:

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

1 个答案:

答案 0 :(得分:2)

在发布的代码中不会遇到两个以上的主要问题。

  • 确定T - 值构造函数的子指针值。
  • 缺少largestIndependentSet()
  • 的返回值

这些的前者很常见,特别是对于C ++的初学者。确保将 nothing 保留为具有不确定的值。在这种情况下,left构造函数中的rightTreeNode(T value)不确定。

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

猜测:编译器愉快地生成了代码,该代码最终处理了由您设置的激活堆栈上的任何事件,作为std::vector<T>。当然,这是不确定的胡言乱语,因为你从未返回过实际的对象。但是std::vector<>的非虚拟析构函数的调用肯定不知道,并且这样做,处理了它认为其成员变量作为有效数据的任何事情,实际上它什么都没有。缺点是:取随机内存,在其上指向std::vector<>析构函数代码,对代码说谎,并说内存中包含一个有效的std::vector<>对象,然后将析构函数松开。

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