0

I wrote a C++ code to build binary search tree. Code compiled correctly, but when I try to run the executable its giving segmentation fault. Below is my code:

    #include <iostream>

using namespace std;

struct Node{
    Node *parent, *right, *left; 
    int data;
};

class bst{
    private:
    Node* root;

    public:
        bst (int data);
        void insert (Node * node, int data);
        void insert (int data);
        Node * search (int data);
        Node * search (Node * node, int data);
        // remove (Node * node, int data);
};

bst::bst (int data){
    root -> data = data;
}

void bst::insert (Node * node, int data){
    if (node == NULL){
        node -> data = data;
    }
    else if (data < node -> data){
        insert (node -> left, data);
    }
    else if (data > node -> data){
        insert (node -> right, data);
    }
}

void bst::insert (int data){
    insert (root, data);
}

Node * bst::search (Node * node, int data){
    if (node == NULL || node -> data == data)
        return node;
    else if (data < node -> data)
        return search (node -> left, data);
    else if (data > node -> data)
        return search (node -> right, data);
}

Node * bst::search (int data){
    search (root, data);
}

int main(){
    cout << "main entry\n";
    bst __bst (10);
    cout << "new causing problem\n";
    bst bst2(1);
//  bst *my_bst = new bst(10);
    cout << "tree created\n";
/*  my_bst -> insert(32);
    my_bst -> insert(3);
    my_bst -> insert(36);
    my_bst -> insert(93);
    my_bst -> insert(23);
    cout << "insertion completed\n";

    if (my_bst -> search(4) == NULL )
        cout << "4 does not exist\n";
    if (my_bst -> search(36) != NULL)
        cout << "36 exists in tree\n";
*/  return 0;
}

While debugging for the problem, I cam across an interesting observation. When main function contains only bst __bst (10); object definition and "new causing problem\n" comment after that, it does not print anything. So I assumed that the first object definition is causing problems. But when I put bst bst2(1); or bst *my_bst = new bst(10); in the main, segmentation fault happens again but not before "new causing problem\n" is printed. So execution did go upto that point. So first object definition did not cause any problem in this case.

Can someone tell what caused segmentation fault and why is this strange thing happening.

Edit: As all of you pointed out that I am trying to dereference a NULL pointer during constructor code, I did the suggested changes and code worked fine. But I have a similar program which is working even without those changes. Below is the code for that:

#include <iostream>

using namespace std;

struct Name{
    string first_name;
    string last_name;
};

class Person{
    public:
    Person (string first_name, string last_name){
            name -> first_name = first_name;
            name -> last_name = last_name;
    }   

    int get_age(){
            return age;
    }   

    void set_age (int new_age){
            age = new_age;
    }   

    string get_first_name(){
            return name -> first_name;
    }   

    string get_last_name(){
            return name -> last_name;
    }   

    private:
    Name * name;
    int age;
};

int main (){ 
    Person prince ("Prince", "Kumar");
    cout << prince.get_first_name() << endl;
    cout << prince.get_age() << endl;
    return 0;
}

In this case the program runs perfectly fine. Did the default constructor for Name allocated some space to the name pointer. I knew that it allocates 0 values to numeric types and NULL to pointer, object and strings. Am I right?

Prince Kumar
  • 388
  • 1
  • 4
  • 15
  • 2
    Side note: In C++, any identifier containing `__` or starting with an `_` followed by a capital letter is reserved. You shouldn't use them. – Shahbaz Apr 15 '13 at 09:24
  • Don't forget to flush your streams (`std::flush` or `std::endl`), otherwise there's no guarantee you'll actually see any output. – Joseph Mansfield Apr 15 '13 at 09:25
  • @sftrabbit, I believe the `\n` would already do that. – Shahbaz Apr 15 '13 at 09:25
  • @Shahbaz: You think of `endl`. The streams should be flushed in their destructors. – Benjamin Bannier Apr 15 '13 at 09:27
  • @honk: I think he's right, and that because stdout tends to be line buffered, it will flush itself when you write a newline to it. – Wug Apr 15 '13 at 09:30
  • 1
    @Wug `'\n'` may or may not flush stdout (it's implementation defined) but `endl` guarantees that the output will be flushed. That's the difference between `'\n'` and `endl`. – john Apr 15 '13 at 09:33
  • @Wug, @Shahbaz: `endl` flushes. `\n` does not necessarily do so. – r_ahlskog Apr 15 '13 at 09:35
  • It may or may not (but does on every platform I've used). – Wug Apr 15 '13 at 09:37
  • @Wug: Use `endl` if you want flushing, no need to guess or hope. – Benjamin Bannier Apr 15 '13 at 09:38
  • It's wrong you got down-voted because your code is so ugly, so I'm up-voting you, But it's ugly, the code. – AK_ Apr 15 '13 at 09:55
  • @Shahbaz what are the uses of __ and _? Can you point out some possible uses or give some links or keywords to search it? – Prince Kumar Apr 16 '13 at 07:40
  • @PrinceKumar, in the case of `__`, usually the standard library writers use them to make sure the identifiers they use in their headers don't clash with yours. This includes header guards, and any symbol that is defined in the header files, but you are not supposed to see them. In the case of _ followed by capital letter, they are often used (at least in C) by the language itself to introduce other keywords without breaking previous conforming codes; for example `_Bool` or `_Generic`. See also [here](http://stackoverflow.com/q/228783/912144) – Shahbaz Apr 16 '13 at 07:54

3 Answers3

0
private:
    Node* root;

root is not initialized in the constructor

bst::bst (int data){
    root -> data = data;
}
Andrey Volk
  • 3,513
  • 2
  • 17
  • 29
0

You are dereferencing a null pointer in the insert() when tree empty case

sr01853
  • 6,043
  • 1
  • 19
  • 39
0

In your constructor you are dereferencing the root which is a pointer without assigning any memory to it, this is undefined behavior:

bst::bst (int data){
  root -> data = data;
}

Something like this would be sufficient:, for this issue

bst::bst (int data) : root( new Node ) 
                      ^^^^^^^^^^^^^^^^ 
{
  root -> data = data;
}

Just use the initialization list to allocate memory. Your insert method also has the same issue:

if (node == NULL){
    node -> data = data;
}

The solution is similar:

node = new Node ;
node->data = data ;

For this to work though you need to initialize right, left and parent correctly, I would advise a constructor in Node for this:

Node() : parent(NULL), right(NULL), left(NULL) {}

These fixes seem to get you a working program.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • you mean "root( new Node )" ? – Andrey Volk Apr 15 '13 at 09:53
  • @AndreyVolk Yes, you are correct, I must have mistyped while editing, thank you. – Shafik Yaghmour Apr 15 '13 at 10:42
  • Thanks for your prompt reply. I am new to Object Oriented programming. But I am still confused about the second part of the question. As the problem is in constructor, the program should end just after the first constructor call. But its printing "new causing problem\n". That seems strange. – Prince Kumar Apr 15 '13 at 11:44
  • @PrinceKumar Well it is undefined behavior which means that anything can happen including not working but not crashing – Shafik Yaghmour Apr 15 '13 at 12:17
  • I am having another doubt. I have written another program in the similar way and its working. Below is the code: – Prince Kumar Apr 16 '13 at 06:42
  • @PrinceKumar Please see this previous SO thread on unassigned pointers http://stackoverflow.com/questions/3101896/c-why-do-unassigned-pointers-point-to-unpredictable-memory-and-not-point-to-nul – Shafik Yaghmour Apr 17 '13 at 17:57
  • @PrinceKumar I am happy you found this answer helpful, you may want to consider [accepting an answer](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) if it helped you solve your problem. – Shafik Yaghmour Nov 11 '14 at 03:25