-4

I'm getting problem with segmentation fault when trying to compile a C++ program, but not sure where the problem lies. I suspect that the problem lies with the .find() ..... could it be the iterator operator < and == which are the comparators for find() that is the issue? I hope that someone can point out to me where they think the problem lies.

The following is part of test01.cpp, where I run it to test the code and use print statements to find out where the problem is:

bool confirmEverythingMatches(const btree<long>& testContainer, const set<long>& stableContainer) {
  cout << "Confirms the btree and the set " 
          "contain exactly the same values..." << endl;


  for (long i = kMinInteger; i <= kMaxInteger; i++) {
    cout << "Start of for-loop to find iterator for comparisons..." << endl;

    if (stableContainer.find(i) != stableContainer.end()) {
      cout << "can find i (" << i << ") in stableContainer!" << endl;
    } else {
      cout << "cannot find i (" << i << ") in stableContainer!" << endl;
    }

    cout << "In between finding i in stable and testContainers..." << endl;

    if (testContainer.find(i) != testContainer.end()) {
      cout << "can find i (" << i << ") in testContainer!" << endl;
    } else {
      cout << "cannot find i (" << i << ") in testContainer!" << endl;
    }

    cout << "Before assigning the find to boolean variables..." << endl;

    bool foundInTree = (testContainer.find(i) != testContainer.end());
    cout << "testContainer.find(i) != testContainer.end()" << endl;


    bool foundInSet = (stableContainer.find(i) != stableContainer.end());
    cout << "stableContainer.find(i) != stableContainer.end()" << endl;

    if (foundInTree != foundInSet) {
      cout << "- btree and set don't contain the same data!" << endl; 
      cout << "Mismatch at element: " << i << endl;
      return false;
    } else {cout << "foundInTree == foundInSet!!!" << i << endl;}
  }
  cout << "- btree checks out just fine." << endl;

  return true;
}

}  // namespace close


/**
 * Codes for testing various bits and pieces. Most of the code is commented out
 * you should uncomment it as appropriate.
 **/
int main(void) {

  // initialise random number generator with 'random' seed
  initRandom();

  cout << "after initRandom().." << endl;

  // insert lots of random numbers and compare with a known correct container
  btree<long> testContainer(99);

  cout << "after specifying max node elements in testContainer.." << endl;

  set<long> stableContainer;

  cout << "after constructing stableContainer.." << endl;

  insertRandomNumbers(testContainer, stableContainer, 1000000);

  cout << "after inserting random numbers into testContainer and for success inserts, also into stableContainer.." << endl;

  btree<long> btcpy = testContainer;

  cout << "after copy assigning a copy of testContainer to btcopy.." << endl;

  confirmEverythingMatches(btcpy, stableContainer);

  cout << "after confirming everything internally matches between testContainer and stableContainer.." << endl;

  return 0; 
}

The output I get when running the program (No problem when compiling) is this:

Confirms the btree and the set contain exactly the same values...
Start of for-loop to find iterator for comparisons...
cannot find i (1000000) in stableContainer!
In between finding i in stable and testContainers...
ASAN:DEADLYSIGNAL
=================================================================
==7345==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000018 (pc 0x000108d132a8 bp 0x000000000000 sp 0x7fff56eee6f0 T0)
    #0 0x108d132a7 in btree<long>::find(long const&) const (test01+0x1000022a7)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV (test01+0x1000022a7) in btree<long>::find(long const&) const
==7345==ABORTING
Abort trap: 6

I also got this error when I tried to run it on another machine:

==29936==ERROR: AddressSanitizer failed to allocate 0x200000 (2097152) bytes of SizeClassAllocator32: 12

I found that when it goes into the find(), it will have the segmentation fault:

/**
 * Identical in functionality to the non-const version of find,
 * save the fact that what's pointed to by the returned iterator
 * is deemed as const and immutable.
 *
 * @param elem the client element we are trying to match.
 * @return an iterator to the matching element, or whatever the
 *         const end() returns if no such match was ever found.
 */
template<typename T> typename btree<T>::const_iterator
btree<T>::find(const T& elem) const {
    std::cout << "CONST ITERATOR'S FIND" << std::endl;

Node *tmp_ = root_;
std::cout << "1" << std::endl;

while(true) {
std::cout << "2" << std::endl;
size_t i;

std::cout << "3" << std::endl;
// go through all elements from root to tail
for (i = 0; i < tmp_->__occupied_size_; ++i) {

    std::cout << "4" << std::endl;

    if (tmp_->__elem_[i] == elem) {

        std::cout << "5" << std::endl;

        // find the elem, return an iterator
        return const_iterator(tmp_, i, this);

        std::cout << "6" << std::endl;

    } else if (tmp_->__elem_[i] > elem) {

        std::cout << "7" << std::endl;

        // elem is not in current Node, go to descendants
        // for the elem.
        if (tmp_->__descendants_ == nullptr) {

            std::cout << "8" << std::endl;
            return cend();
            std::cout << "9" << std::endl;

        } else {

            std::cout << "10" << std::endl;
            tmp_ = tmp_->__descendants_[i];
            std::cout << "11" << std::endl;
            break;
                }
            }
        }
        // handling boundaries cases
        if (i == tmp_->__occupied_size_) {
            std::cout << "12" << std::endl;
            if (tmp_->__descendants_[i] == nullptr) {
                std::cout << "13" << std::endl;
                return cend();
                std::cout << "14" << std::endl;
            } else {
                std::cout << "15" << std::endl;
                tmp_ = tmp_->__descendants_[i];
            }
        }
    }
}

The print statements for this find is:

CONST ITERATOR'S FIND
1
2
3
4
4
7
10
11
2
3
4
7
10
11
ASAN:DEADLYSIGNAL
iteong
  • 715
  • 3
  • 10
  • 26

2 Answers2

1

Ok, so based on the implementation of this find function, I think the problem might be located in

if (tmp_->__descendants_ == nullptr) {
    std::cout << "8" << std::endl;
    return cend();
    std::cout << "9" << std::endl;
} else {
    std::cout << "10" << std::endl;
    tmp_ = tmp_->__descendants_[i];
    std::cout << "11" << std::endl;
    break;
}

and then

// handling boundaries cases
if (i == tmp_->__occupied_size_) {
    std::cout << "12" << std::endl;
    if (tmp_->__descendants_[i] == nullptr) {
        std::cout << "13" << std::endl;
        return cend();
        std::cout << "14" << std::endl;
    } else {
        std::cout << "15" << std::endl;
        tmp_ = tmp_->__descendants_[i];
    }
}

So, You are checking if tmp->__descendants_ is not null. If it is not, then you set tmp_ = tmp_->descendants_[i];

Note: you are just checking __descendants_ pointer to be null or not, you are not checking the __descendants_ [i] if it is null!

What if the tmp->__descendants_[i] is null (or gets out of the descendants array)?

If that value is null, then tmp_->occupied_size_ might give you segfault.

Note2: For some reason you are using same index "i" for iterating through __elem_ and __descendants_. I am not sure, how descendants are created, but it might be also a problem here.

1

This is why debuggers exist. Run your program in the debugger, let the program fail, and then the debugger will tell you where and why it's gone wrong.

It looks like you've got potentially a lot of code to trawl through, which no one here will really want to do as it's not a concise question.

Good luck!

UKMonkey
  • 6,941
  • 3
  • 21
  • 30