kpeeters / tree.hh

An STL-like C++ header-only tree library
GNU General Public License v3.0
132 stars 31 forks source link

Non initialized primitive data in head and feet interfer with comparison (<=, <, etc.) based algoritms during search #8

Open rdebroiz opened 3 years ago

rdebroiz commented 3 years ago

It appears that head and feet nodes has a data member which is not initialized in the case where tree is templated on primitives. In some cases those data seems to interfere with search algorithms based on value comparison (lower_bound, upper_bound) when they take 'head' level sibling_iterator (the algorithm then randomly returns what looks like a default iterators instead of an iterator at the end position). it can be fixed by manually initializing those data with proper values.

step to reproduce:

#include <algorithm>
#include "tree.hh"

int main(int argc, char* argv[]) {
    typedef tree<char> Tree;
    Tree tree;

    // replace min by max to avoid the segfault
    tree.head->data = std::numeric_limits<char>::min();
    tree.feet->data = std::numeric_limits<char>::min();

    Tree::sibling_iterator it = tree.begin();
    it = tree.insert(it, 0);
    for (char c = 0; ++c; c < std::numeric_limits<char>::max()) {
        std::cout << "inserting char: " << (int) c << std::endl;
        it = std::lower_bound(it, it.end(), std::numeric_limits<char>::max()); 
        // here depending of what is c and what are head->data and feet->data the returned iterator
        // may be a default one instead of an iterator at it.end().
        it = tree.insert(it, c);
    }
    return EXIT_SUCCESS;
}

Inspection of the iterator returned by std::lower_bound before the segfault:

it = {tree<char, std::allocator>::sibling_iterator} 
 tree<char, std::allocator<tree_node_<char> > >::iterator_base = {tree<char, std::allocator>::iterator_base} 
  node = {tree<char, std::allocator>::tree_node * | 0x0} NULL
  skip_current_children_ = {bool} false
 parent_ = {tree<char, std::allocator>::tree_node * | 0x0} NULL