【问题标题】:terminated by signal SIGSEGV (Address boundary error) when dealing with iterators处理迭代器时由信号 SIGSEGV(地址边界错误)终止
【发布时间】:2016-09-10 23:17:28
【问题描述】:

我正在尝试实现归并排序算法。首先,我正在尝试创建合并方法。我正在使用向量并利用迭代器。但是merge 函数中的while 主体会导致此错误:

“./a.out”被信号 SIGSEGV 终止(地址边界错误)

这是代码

#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;
}

【问题讨论】:

  • 如果first_it != endsecond_it == end,你的while 循环会发生什么?
  • @PaulMcKenzie sorted_vect 与被迭代的向量不同。
  • @RichardCritten 好的,我现在看到了。

标签: c++ c++11 iterator mergesort segmentation-fault


【解决方案1】:

通常当进程尝试访问未分配给该特定进程的内存时会引发 SIGSEGV。引发 SIGSEGV 的主要原因是取消引用无效指针。在您的情况下,当您取消引用 first_it 或 second_it 以检查其值时,会发生这种情况,而您已到达该列表的末尾。

您至少需要三个更改:

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:您应该检查是否到达任何列表的末尾:您应该使用 and (&&) 不或 (||)。这将消除 SIGSEGV 错误。

2&3:您应该将剩余列表的其余部分添加到合并列表的末尾,而不是在最后一个元素之前。

可选更改:

1- 你不需要 sorted_it 变量(你没有使用它)

2- 你不必检查是否相等,如果值相等,你可以插入其中任何一个,循环的下一次迭代就会发挥作用。

3- 您不必检查哪个列表到达其末尾,您可以合并每个列表的其余部分。

以上都体现在这里:

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;
}

【讨论】:

    【解决方案2】:
    while(first_it != first_vect.end() || second_it != second_vect.end())
    

    您正在迭代直到:

    1. first_it 等于 first_vect.end() AND

    2. second_it 等于second_vect.end()

    这两个条件都必须为真。例如,如果first_it 已到达first_vect.end(),则迭代将继续,直到second_it 到达其向量的末尾。

      if(*first_it < *second_it) {
    

    正如我刚刚解释的,first_it 现在可以等于其向量的 end() 迭代器。在这种情况下,在此处取消引用会导致未定义的行为。

    第二个向量的迭代器也是如此。

    您的逻辑没有考虑到任一迭代器已到达其向量的end() 的可能性。

    一种解决方法是将|| 转换为&amp;&amp;,然后在最后添加额外的代码以将任一向量中的任何剩余值附加到输出向量。

    解决此问题的另一种方法是调整if() 条件以考虑迭代器可能是end() 值的可能性,并相应地继续。对于第一个向量:

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

    但是这个逻辑在这里变得有点复杂(if 条件都必须以这种方式检查两个迭代器的边缘情况)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      • 1970-01-01
      • 2011-06-26
      • 1970-01-01
      相关资源
      最近更新 更多