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

6l7fqoea  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(144)

我写了C++代码:

  1. #include <iostream>
  2. #include <queue>
  3. #include <stack>
  4. #include <vector>
  5. #include <unordered_map>
  6. #include <algorithm>
  7. using namespace std;
  8. template <class T>
  9. class TreeNode {
  10. public:
  11. T data;
  12. TreeNode<T> *left, *right;
  13. TreeNode() {
  14. data = {};
  15. left = right = NULL;
  16. }
  17. TreeNode(T data) {
  18. this->data = data;
  19. }
  20. };
  21. template <class T>
  22. class BinaryTree {
  23. public:
  24. TreeNode<T> *root;
  25. vector<T> _largestIndependentSet(TreeNode<T> *root) {
  26. static unordered_map< TreeNode<T>*, vector<T> > table;
  27. if(!root)
  28. return {};
  29. if(table.find(root) != table.end())
  30. return table[root];
  31. vector<T> lis = {}, lis_left = {}, lis_right = {},
  32. lis_nrl_left = {}, lis_nrl_right = {}, lis_nrr_left = {}, lis_nrr_right = {};
  33. // Leaf
  34. if(!root->left && !root->right) {
  35. lis.push_back(root->data);
  36. }else{
  37. if(root->left){
  38. lis_left = _largestIndependentSet(root->left);
  39. lis_nrl_left = _largestIndependentSet(root->left->left);
  40. lis_nrl_right = _largestIndependentSet(root->left->right);
  41. }
  42. if(root->right){
  43. lis_right = _largestIndependentSet(root->right);
  44. lis_nrr_left = _largestIndependentSet(root->right->left);
  45. lis_nrr_right = _largestIndependentSet(root->right->right);
  46. }
  47. if( lis_left.size() + lis_right.size() >
  48. lis_nrl_left.size() + lis_nrl_right.size() +
  49. lis_nrr_left.size() + lis_nrr_right.size() + 1 ){ // don't keep root
  50. lis.insert(lis.end(), lis_left.begin(), lis_left.end());
  51. lis.insert(lis.end(), lis_right.begin(), lis_right.end());
  52. }
  53. else {
  54. lis.insert(lis.end(), lis_nrl_left.begin(), lis_nrl_left.end());
  55. lis.insert(lis.end(), lis_nrl_right.begin(), lis_nrl_right.end());
  56. lis.insert(lis.end(), lis_nrr_left.begin(), lis_nrr_left.end());
  57. lis.insert(lis.end(), lis_nrr_right.begin(), lis_nrr_right.end());
  58. lis.push_back(root->data);
  59. }
  60. }
  61. cout<<"Calculated Results for: "<<root->data<<": ";
  62. for_each(lis.begin(), lis.end(), [](T data) {
  63. cout<<data<<" ";
  64. });
  65. cout<<"\n";
  66. table[root] = lis;
  67. return table[root];
  68. }
  69. void largestIndependentSet() {
  70. vector<T> lis = _largestIndependentSet(this->root);
  71. for_each(lis.begin(), lis.end(), [](T data) {
  72. cout<<data<<" ";
  73. });
  74. }
  75. };
  76. int main() {
  77. BinaryTree<int> bt;
  78. TreeNode<int> *root = new TreeNode<int>(10);
  79. root->left = new TreeNode<int>(7);
  80. root->right = new TreeNode<int>(15);
  81. root->left->left = new TreeNode<int>(9);
  82. root->left->right = new TreeNode<int>(12);
  83. root->right->left = new TreeNode<int>(6);
  84. root->right->right = new TreeNode<int>(11);
  85. root->left->left->left = new TreeNode<int>(20);
  86. root->right->left->right = new TreeNode<int>(5);
  87. root->left->left->left->left = new TreeNode<int>(22);
  88. root->left->left->left->right = new TreeNode<int>(21);
  89. root->right->left->right->left = new TreeNode<int>(4);
  90. root->right->left->right->right = new TreeNode<int>(3);
  91. bt.root = root;
  92. bt.largestIndependentSet();
  93. return 0;
  94. }

字符串
我在Cygwin上使用g++ 5.4.0编译了它:

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


问题是,在递归函数_largestIndependentSet()完成后,最后一次打印给了我正确的答案。但在那之后,我得到了这个错误:Aborted(core dumped),并且largestIndependentSet()中的打印没有执行。
这是令人费解的,因为我的逻辑似乎是正确的,这是什么原因造成的呢?
PS:如果我编译它与c++14标志它运行罚款o_O:

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

qc6wkl3g

qc6wkl3g1#

在发布的代码中不涉及两个以上的主要问题。

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

前一种情况很常见,尤其是对于C的初学者。确保您没有留下任何不确定的值。在本例中,TreeNode(T value)构造函数中的leftright都是不确定的。
后者非常重要。函数largestIndependentSet()声称它返回一个向量,但实际上根本没有return。同样,这调用了 * 未定义的行为 *。从那里我可以推测,但注意这就是全部:推测:
猜测:编译器很高兴地生成了代码,最终将激活堆栈上的任何内容都视为std::vector<T>,而不是由您取消设置。当然,这是不确定的胡言乱语,因为您从未返回过实际对象。但是std::vector<>的非虚拟析构函数的调用肯定不知道这一点,并且在这样做的过程中,把任何碰巧占据它认为是它的成员变量的东西都当作有效数据,而实际上它不是。简短的说:取随机内存,指向std::vector<>析构函数代码,欺骗代码说内存中有一个有效的std::vector<>对象,然后松开析构函数。
至于为什么编译器没有 error。嗯,通常在C或C
中,做一些不明智的事情并不是什么错误。编译器希望你对你正在做的事情有足够的了解,在这种情况下,不存在语言冲突,所以它给了你怀疑的好处。然而,在大多数现代编译器上,把你的编译器警告级别提高到学究式的高度,(icc,gcc,clang和msvc)* 警告 * 你丢失了返回值。这些警告是有原因的,我强烈支持把它们打开 * 并把它们当作错误处理(也是编译器的一个选项)。

相关问题