使用以向量为输入的递归方法时的分段错误

Posted

技术标签:

【中文标题】使用以向量为输入的递归方法时的分段错误【英文标题】:Segmentation fault when using recursive method taking vector as input 【发布时间】:2017-09-10 11:47:39 【问题描述】:

我正在尝试使用递归制作一个非常简单的过滤器,但由于某种原因,我不断收到这些 Seg Fault。

#include <iostream>
#include <vector>
#include <math.h>

class FilterGeneric 
public:
    std::vector<int> filter(std::vector<int>& v, std::vector<int>::iterator i); //set i=v.begin() in main
private:
    virtual bool g(int x) =0;
    std::vector<int> result;
;

std::vector<int> FilterGeneric::filter(std::vector<int>& v, std::vector<int>::iterator i)   
    if (i==v.end()) 
        return result;
       else    
        if (g(*i)==true)    
            result.push_back(*i);
            i++;
            return filter(v,i);
           else    
            i++;
            return filter(v,i);
        
    


class FilterOdd : public FilterGeneric  
private:
    bool g(int x);
;

bool FilterOdd::g(int x)    
    if ((x%2)!=0)   
        return true;
       else    
        return false;
    


class FilterNonPositive : public FilterGeneric  
private:
    bool g(int x);
;

bool FilterNonPositive::g(int x)    
    if (x<0)   
        return true;
       else    
        return false;
    


class FilterForTwoDigitPositive : public FilterGeneric  
private:
    bool g(int x);
;

bool FilterForTwoDigitPositive::g(int x)    
    if (x>=10)   
        return true;
       else    
        return false;
    


int main()  

    std::vector<int> v;
    std::vector<int>::iterator it=v.begin();

    for (int i=0;i<20;i++)  
        v.push_back(pow(-1,i)*i);
    

    std::cout<<std::endl;

    FilterNonPositive fnp;
    FilterForTwoDigitPositive ftd;

    FilterGeneric *f1=&fnp;
    FilterGeneric *f2=&ftd;

    std::vector<int> r1;
    std::vector<int> r2;

    r1=f1->filter(v,it);
    for (it=r1.begin();it!=r1.end();it++)   
        std::cout<<*it<<" ";
    
    r2=f2->filter(v,it);
    for (it=r2.begin();it!=r2.end();it++)   
        std::cout<<*it<<" ";
    


【问题讨论】:

堆栈空间不足? @user0042 我很抱歉我缺乏知识,但是有可能这么容易用完堆栈空间吗?我的意思是,这么简单的代码?我是说,我在这台电脑上玩游戏。 堆栈空间非常有限,使用递归函数调用时很容易用完。而是使用std::stack 和一个简单的循环。 @ViệtEngland我看不出堆栈空间与您的问题有任何关系。然而,Employed Russian 发布的答案肯定相关,我强烈建议您阅读并点击其中的链接。 【参考方案1】:

错误就在这里:

std::vector<int> v;
std::vector<int>::iterator it=v.begin();

for (int i=0;i<20;i++)  
    v.push_back(pow(-1,i)*i);  // invalidates all iterators into "v"

...
r1=f1->filter(v,it);  // using invalidated "it"

问题是v.push_back()使所有迭代器无效如果向量需要调整大小。来自documentation:

如果新的 size() 大于 capacity() 则所有迭代器和引用(包括过去的迭代器)都将失效。否则只有过去的迭代器无效。

v 初始化后通过移动 it 初始化来纠正上述错误后,还有其他错误。

如果您使用g++ 构建,您可以使用-D_GLIBCXX_DEBUG 来帮助您找到此类错误。

【讨论】:

有趣的是,pow 函数返回一个浮点值。提供的示例可能存在精度问题,因为将结果转换为浮点(用于参数)转换回整数。

以上是关于使用以向量为输入的递归方法时的分段错误的主要内容,如果未能解决你的问题,请参考以下文章

推送到成员向量时的段错误

使用向量将给定表达式转换为波兰符号时的运行时错误

C++ 程序结束时的 thread_local 向量分段错误

在访问向量矢量的元素时的分段错误

分段错误:在 C++ 中弹出向量时出现 11

C ++中动态分配的向量中的分段错误