简体   繁体   中英

terminated by signal SIGSEGV (Address boundary error) when dealing with iterators

I'm trying to implement merge sort algorithm. First I'm trying to create the merge method. I'm using vectors and utilizing iterators. But the while body in merge function causes this error:

“./a.out” terminated by signal SIGSEGV (Address boundary error)

Here's the code

#include <iostream>
#include <vector>

std::vector<int> merge(std::vector<int> &, std::vector<int> &);

int main()
{
  std::vector<int> vect {1,3,5,7};
  std::vector<int> vect2 {2,3,6,8};
  std::vector<int> temp_vect = merge(vect, vect2);
  for(int num: temp_vect) {
    std::cout << num  << std::endl;
  }

}

std::vector<int> merge(std::vector<int> & first_vect, std::vector<int> & second_vect)
{
  std::vector<int> sorted_vect;
  auto sorted_it = sorted_vect.begin();
  auto first_it = first_vect.begin(), second_it = second_vect.begin();

  while(first_it != first_vect.end() || second_it != second_vect.end()) {
      if(*first_it < *second_it) {
        sorted_vect.push_back(*first_it);
        first_it++;
      } else if(*first_it > *second_it) {
        sorted_vect.push_back(*second_it);
        second_it++;
      } else {
        sorted_vect.push_back(*first_it);
        sorted_vect.push_back(*second_it);
        first_it++; second_it++;
      }
  }

  if(first_it == first_vect.end()) {
    //end of first_vect reached
    //inserting the rest of second_vect
    sorted_vect.insert(sorted_vect.end() - 1, second_it, second_vect.end());
  } else if (second_it == second_vect.end()) {
    //end of second_vect reached
    //inserting the rest of first_vect
    sorted_vect.insert(sorted_vect.end() - 1, first_it, first_vect.end());
  }

  return sorted_vect;
}

Usually SIGSEGV is raised when a process tries to access a memory which is not assigned to that specific process. The main reason of raising SIGSEGV is dereferencing an invalid pointer. In your case it happens when you dereferencing first_it or second_it to check its value, while you reached the end of that list.

You need at least three changes:

1: line 23- while(first_it != first_vect.end() && second_it != second_vect.end())
2: line 40- sorted_vect.insert(sorted_vect.end(), second_it, second_vect.end());
3: line 44- sorted_vect.insert(sorted_vect.end(), first_it, first_vect.end());

1: You should check to see if you reached the end of any of lists: you should use and (&&) not or (||). This will remove SIGSEGV error.

2&3: You Should add the rest of remaining list to the end of merged list, not before the last element.

Optional changes:

1- You don't need sorted_it variable (you are not using it)

2- You don't have to check for equality, if the values are equal, you may insert any one of them and the next iteration of loop will do the magic.

3- You don't have to check which list reaches its end, you may combine the rest of each list.

All of the above is reflected here:

std::vector<int> merge(std::vector<int> & first_vect, std::vector<int> & second_vect)
{
      std::vector<int> sorted_vect;
      auto first_it = first_vect.begin(), second_it = second_vect.begin();

      while(first_it != first_vect.end() && second_it != second_vect.end()) {
           if(*first_it < *second_it) {
               sorted_vect.push_back(*first_it);
               first_it++;
           } else {
               sorted_vect.push_back(*second_it);
               second_it++;
           }
      }
      sorted_vect.insert(sorted_vect.end(), first_it, first_vect.end());
      sorted_vect.insert(sorted_vect.end(), second_it, second_vect.end());
      return sorted_vect;
}
while(first_it != first_vect.end() || second_it != second_vect.end())

You are iterating until:

  1. first_it is equal to first_vect.end() AND

  2. second_it is equal to second_vect.end()

Both of these conditions must be true. If first_it has reached first_vect.end() , for example, iteration will continue, until second_it reaches the end of its vector.

  if(*first_it < *second_it) {

As I've just explained, first_it can now be equal to the end() iterator of its vector. In which case dereferencing it here results in undefined behavior.

The same thing applies to the second vector's iterator.

Your logic fails to take into consideration the possibility that either iterator has reached the end() of its vector.

One fix would be to turn the || into && , then add additional code in the end to append any remaining values in either vector to the output vector.

Another way to fix this would be to adjust the if() conditions to take into account the possibility that the iterator can possibly be the end() value, and proceed accordingly. For the first vector that would be:

  if(second_it == second_vect.end() ||
      (first_it != first_vect.end() && *first_it < *second_it)) {

But this logic becomes a bit convoluted here (both if conditions must check the edge case for both iterators, in this fashion).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM