0

I am implementing Red-Black Trees and I cannot seem to debug a segmentation fault that occurs when calling the fixup() function. The backtrace from gdb is provided below. The functions can be seen below the backtrace. Is it incorrect to pass a pointer to the fixup() function or do I need to de-reference this node? Would it be better practice to pass the Node itself then create a new Nodeptr object? Thank you for your time.

#0  0x0000000000403f32 in RBT::fixup(RBT::Node*) ()
#1  0x0000000000403d7a in RBT::insert(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) ()
#2  0x0000000000402950 in insertNodesFromFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >) ()
#3  0x0000000000402712 in selectStructure() ()
#4  0x00000000004023df in main ()
class RBT{
        private:
                class Node;
                typedef Node * Nodeptr;

                class Node{

                        public:
                                string key;
                                Nodeptr parent;
                                Nodeptr left;
                                Nodeptr right;
                                char color;

                                Node(Nodeptr const left, Nodeptr const parent, const string key, const char color, Nodeptr const right)
                                        :left(left), parent(parent), key(key), color(color), right(right)
                                {}//end Node

                };

                Nodeptr root;

        public:

                RBT(): root(nullptr) {}

                Nodeptr createNode(Nodeptr const left, Nodeptr const parent, const string key, const char color, Nodeptr const right){
                        return new Node(left, parent, key, color, right);
                }//end createNode()

                void insert(string key){
                        Nodeptr y = nullptr;
                        Nodeptr x = root;

                        Nodeptr z = createNode(nullptr, nullptr, key, 'R', nullptr);
                        cout << "CREATE NODE" << endl;

                        while(x != nullptr){
                                y = x;
                                if(z->key < x->key) {
                                        x = x->left;
                                } else {
                                        x = x->right;
                                }
                        }

                        z->parent = y;
                        if(y == nullptr)         { root = z;     }
                        else if(z->key < y->key) { y->left = z;  }
                        else                     { y->right = z; }

                        z->left = nullptr;
                        z->right = nullptr;
                        z->color = 'R';

                        cout << "BEFORE FIXUP" << endl;
                        fixup(z);

                }

                void fixup(Nodeptr z){

                        while(z->parent->color == 'R'){
                                if(z->parent == z->parent->parent->left){
                                        Nodeptr y = z->parent->parent->right;

                                        if(y->color == 'R'){
                                                z->parent->color = 'B';
                                                y->color = 'B';
                                                z->parent->parent->color = 'R';
                                                z = z->parent->parent;
                                        } else {
                                                if(z == z->parent->right){
                                                        z = z->parent;
                                                        leftRotate(z);
                                                }

                                                z->parent->color = 'B';
                                                z->parent->parent->color = 'R';
                                                rightRotate(z->parent->parent);

                                        }
                                } else{
                                        Nodeptr y = z->parent->parent->left;

                                        if(y->color == 'R'){
                                                z->parent->color = 'B';
                                                y->color = 'B';
                                                z->parent->parent->color = 'R';
                                                z = z->parent->parent;
                                        } else {
                                                if(z == z->parent->left){
                                                        z = z->parent;
                                                        rightRotate(z);
                                                }

                                                z->parent->color = 'B';
                                                z->parent->parent->color = 'R';
                                                leftRotate(z->parent->parent);
                                        }
                                }
                        }
                        root->color = 'B';
                }
  • 3
    Your ability to generate a backtrace already shows that you have more debugging skill, ability, and knowledge than most people who ask these kinds of questions here. So all you have to do is just finish your job: use gdb to print out the values of all variables, perhaps at different levels of the stack frame, in order to get the entire picture of the state of your program, and then determine why it crashed. `gdb` has commands for navigating the stack frame, and printing variables. Use them, and never have to ask this kind of a question here, again, because you'll figure it out yourself. – Sam Varshavchik Feb 22 '20 at 19:32
  • Please provide a [mre] – Alan Birtles Feb 22 '20 at 19:34
  • @SamVarshavchik What could possibly cause it to segfault from a single function call? That's what I'm confused about. This function call only happens once and it never even enters the `fixup()`. – user6547984165 Feb 22 '20 at 19:40
  • The first thing you do in `fixup` is dereference `z->parent`. This will be a nullptr for the root (first node inserted). What bad address is causing the segfault? – 1201ProgramAlarm Feb 22 '20 at 19:54
  • The address `0x0000000000403f32` is causing the segfault. @1201ProgramAlarm – user6547984165 Feb 22 '20 at 20:03
  • Give me a function that doesn't do 100% error checking and validation, and I'll give you a way to segfault it "from a single function call". – Sam Varshavchik Feb 22 '20 at 21:06
  • @SamVarshavchik From further debugging it seems like the code cannot access memory of `z->parent = y` where `y = nullptr` which is why `z->parent` is not working properly. This means the `while(z->parent->color == 'R')` will never work since `z->parent` is `nullptr`. However, this algorithm comes straight from a textbook. Would it be possible to check to see if `z->parent == nullptr` and then skip the `while` loop? – user6547984165 Feb 22 '20 at 21:32
  • I'm not familiar with the algorithm in question; but looks like you've determined the immediate reason for the crash. Now that you're understand the immediate cause, you need to figure out if you're not implementing the algorithm correctly, or if the algorithm is logically flawed and what the flaw is, and go from there. – Sam Varshavchik Feb 22 '20 at 22:32
  • Compile with -O0 -g. Run with gdb. Get frame 0 (> frame 0). Get line (> line). You will see the exact line that causes a segfault. – Askold Ilvento Feb 22 '20 at 23:25

0 Answers0