1

I am trying to implement a tree structure and I am storing pointers to children nodes in an array. I am trying to add nodes but they aren't working as expected. For example, somewhere in the code the pointer gets the value 0xfeeefeeefeeefeee and I encounter a segmentation fault. I am not too familiar with C++ pointers and memory allocation. Can someone tell me what is the issue?

Code:

#include <iostream>
#include <vector>

using namespace std;

class Node{
    public:
    vector <Node*> children = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
};

Node parent;

/*
void changePointer(Node **a, Node* b){
    *a = b;
}
*/

void add_to_visited(vector <vector <vector<int>>> arr){
    Node* curr = &parent;
    for (int face=0;face<6;face++){
        for (int row=0;row<2;row++){
            for (int col=0;col<2;col++){
                if (curr->children[arr[face][row][col]]==nullptr){
                    Node temp;
                    curr->children[arr[face][row][col]]=&temp;
                }
                curr = curr->children[arr[face][row][col]];
                //changePointer(&curr, curr->children[arr[face][row][col]]);

            }
        }
    }
}

int main(){
    vector <vector <vector <int>>> arr = 
    {
        {
            {4, 1},
            {2, 4}
        },
        {
            {5, 3},
            {5, 4}
        },
        {
            {2, 0},
            {1, 5}
        },
        {
            {0, 1},
            {2, 0}
        },
        {
            {1, 3},
            {3, 0}
        },
        {
            {5, 2},
            {3, 4}
        }
    };

    add_to_visited(arr);


}
  • 3
    ***0xFEEEFEEE : Used by Microsoft's HeapFree() to mark freed heap memory***: [https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations](https://stackoverflow.com/questions/127386/in-visual-studio-c-what-are-the-memory-allocation-representations) – drescherjm Jun 22 '21 at 02:33
  • 2
    `Node temp; curr->children[arr[face][row][col]]=&temp;` looks like a dangling pointer here. You can not store the address of a local variable which will go out of scope. The scope of `temp` ends at the next `}` – drescherjm Jun 22 '21 at 02:35
  • [When and why will a compiler initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?](https://stackoverflow.com/q/370195/995714): *0xFEEEFEEE: OS fill heap memory, which was marked for usage, but wasn't allocated by `HeapAlloc()` or `LocalAlloc()`. Or that memory just has been freed by `HeapFree()`.* – phuclv Jun 22 '21 at 03:18

1 Answers1

1

As the comment pointed out: It's a dangling pointer, the local variable doesn't live long enough (The local variable temp will be destroyed after the innermost if statement). It can be fixed by using pointers to heap objects(smart pointers here)

#include <iostream>
#include <memory>
#include <vector>

using namespace std;

class Node {
 public:
  static inline size_t kNodes = 6;
  Node() { children.resize(kNodes); }
  vector<std::unique_ptr<Node>> children;
};

Node parent;

/*
void changePointer(Node **a, Node* b){
    *a = b;
}
*/

void add_to_visited(vector<vector<vector<int>>> arr) {
  Node* curr = &parent;
  for (int face = 0; face < 6; face++) {
    for (int row = 0; row < 2; row++) {
      for (int col = 0; col < 2; col++) {
        if (curr->children[arr[face][row][col]] == nullptr) {
          curr->children[arr[face][row][col]] = std::make_unique<Node>();
        }
        curr = curr->children[arr[face][row][col]].get();
      }
    }
  }
}

int main() {
  vector<vector<vector<int>>> arr = {{{4, 1}, {2, 4}}, {{5, 3}, {5, 4}},
                                     {{2, 0}, {1, 5}}, {{0, 1}, {2, 0}},
                                     {{1, 3}, {3, 0}}, {{5, 2}, {3, 4}}};

  add_to_visited(arr);
}

Tips for code smell:

It's not recommended to use hardcoded number 6,2,2 in the loop(Once we changed the input data, we can forget to change the loops here), we can use arr.size(), arr[0].size()... to make it more robust and easy to maintain.

Online Demo

prehistoricpenguin
  • 6,130
  • 3
  • 25
  • 42
  • How do you run your code on that demo platform ? – Job_September_2020 Jun 22 '21 at 02:59
  • 1
    @Job_September_2020 Just type on the site or paste the code from the local machine to the site, it will automatically run the build result if you checked the run the compiled output :) – prehistoricpenguin Jun 22 '21 at 03:00
  • When I click on your link, I can see your code exists on the window. Which button do I need to press to run your code ? – Job_September_2020 Jun 22 '21 at 03:02
  • When you say std::make_unique() creates a smart pointer, does it mean we don't need to delete it after we are done , and the pointer will delete itself ? – Job_September_2020 Jun 22 '21 at 03:05
  • 1
    @Job_September_2020 There is an option just on the top of the disassembly code, `run the compiled output`, you can have a try. Smart pointer doesn't need to be deleted manually, you are right. – prehistoricpenguin Jun 22 '21 at 03:06
  • Thanks for the info. BTW, is there any situation we should use new/delete instead of std::make_unique() ? – Job_September_2020 Jun 22 '21 at 03:13
  • @Job_September_2020 We should prefer to use smart pointers instead of `new/delete` anywhere, manage the pointer lifetime is error-prone and hard to maintain. – prehistoricpenguin Jun 22 '21 at 03:15
  • 1
    @Job_September_2020 There are awesome answers on smart pointers: https://stackoverflow.com/questions/106508/what-is-a-smart-pointer-and-when-should-i-use-one – prehistoricpenguin Jun 22 '21 at 06:48