g ++ -O2 флаг, дающий ошибку сегментации - PullRequest
0 голосов
/ 16 апреля 2020

Программа ниже представляет собой BST-дерево, которое отлично работает в неоптимизированных настройках, но выдает SIGSEGV при особых обстоятельствах. Так как мои навыки отладки не распространяются на сборку, я могу использовать некоторые данные для определения причины этой ошибки. Ниже приведен полный код, чтобы его можно было воспроизвести. В этом нет ничего необычного, есть структура узла для хранения данных узла, простая операция вставки и метод для подтверждения высоты дерева.

#include <iostream>
#include <cstdlib>

using namespace std;

typedef struct avl_tree_node //node data
{
  int data;
  int balance{0};
  avl_tree_node *left{NULL};
  avl_tree_node *right{NULL};
  avl_tree_node *parent{NULL};

}node;

class avl
{
private:
  node *root;
  int get_height(node *head) //calculates the height
  {
    if (head == NULL)
      return -1;

    int l_height = get_height(head->left);
    int r_height = get_height(head->right);

    if (l_height > r_height)
      return l_height+1;

    return r_height+1;
  }

  void unbalanced_insert(node *head, int item); //method definition for a simple insert

public:
  avl(int data)
  {
    root->data = data;
    root->parent = NULL;
    root->left = NULL;
    root->right = NULL;
  }

  int height() //gives the height
  {
    return get_height(root);
  }

  void unbalanced_insert(int item) //wrapper
  {
    unbalanced_insert(root, item);
  }

};

void avl::unbalanced_insert(node *head, int item) //inserts node to the tree
{
  //cout << "stepped" << endl;
  if (item > head->data)
    {
      if (head->right == NULL)
    {
      head->right = (node*)malloc(sizeof(node));
      head->right->data = item;
      head->right->parent = head;
      head->right->left = NULL;
      head->right->right = NULL;
      head->balance = 1;
      return;
    }
      unbalanced_insert(head->right, item);
      head->balance++;
      return;
    }

  else
    {
      if (head->left == NULL)
    {
      head->left = (node*)malloc(sizeof(node));
      head->left->data = item;
      head->left->parent= head;
      head->left->left = NULL;
      head->left->right = NULL;
      head->balance = -1;
      return;
    }
      unbalanced_insert(head->left, item);
      head->balance--;
      return;
    }
}

int main()
{
  avl a(0);

  for (int i = 1; i < 5; i++) //works until i < 4
    {
      a.unbalanced_insert(i);
    }
  cout << a.height() << endl;

  return 0;
}

В нормальных условиях я был бы рад, что это работает с неоптимизированными флагами, но я должен построить это с указанием c флагов. Одним из таких является флаг -O2. Ошибка сегментации возникает между конструкцией объекта avl a(0) и формой l oop внутри сети. Ошибка также, кажется, зависит от логической проверки для l oop. Это прекрасно работает, если i < 4 и выполняется с: g++ avl.cpp -g -O2 -o program && ./program

Ответы [ 2 ]

4 голосов
/ 16 апреля 2020

Одна очевидная проблема, и она возникает при самом первом вызове функции в main, то есть avl a(0):

root->data = data;

root не инициализируется, таким образом, поведение не определено.

0 голосов
/ 16 апреля 2020

Я полагаю, когда создается экземпляр объекта avl.

 avl a(0);

вызывается конструктор класса, как показано ниже.

avl(int data)
  {
    root->data = data;
    root->parent = NULL;
    root->left = NULL;
    root->right = NULL;
  }

Но здесь я вижу root указатель не выделил любую память

...