为什么在循环条件中使用'<='而不是'<'会产生分段错误[SIGSEGV]?

时间:2019-12-12 11:31:30

标签: c++ data-structures segmentation-fault runtime-error

我正在DECEMBER竞赛-https://www.codechef.com/DEC19B/problems/BINADD中解决codechef的问题。我在代码中的某个地方放了这个循环:

    for(i=0;i<=(pos.size()-2);i++)
    {
    if(pos[i]<0) 
        continue;
    else if(len<(pos[i]-pos[i+1])) 
        len=pos[i]-abs(pos[i+1]);
    } 

这里pos是一个向量,声明为: vector<int> pos;

对于这些值,代码显示一个SIGSEGV:

  

pos的大小= 1,pos [0] = 0,len = 0

但是,如果我在循环中将i<=(pos.size()-2)替换为i<(pos.size()-1),则会发生 NO SIGSEGV。有人有解释吗

注意: 1)完整代码:

#include <bits/stdc++.h>
using namespace std;

void func()
{   
    int i=0,len=0,index=0;
    string a,b;
    cin>>a>>b;

    if(b=="0") {std::cout << 0 << std::endl;return;}
    else if(a=="0") {std::cout << 1 << std::endl;return;}
    int n1,n2;
    n1=a.length();
    n2=b.length();
    if(n1<n2)
    { 
        i=n2-n1;
        while(i--)
            a="0"+a;
    }
    else 
    {   
        i=n1-n2; 
        while(i--) 
            b="0"+b;
    }
    std::vector<int> pos;
    i=a.length();
    while(i--)
    {
        if(a[i]=='0'&&b[i]=='0')
            pos.push_back(-i);
        if(a[i]=='1'&&b[i]=='1')
            pos.push_back(i);
    }
    for(i=0;i<=(pos.size()-2);i++)
    {
        if(pos[i]<0) 
            continue;
        else if(len<(pos[i]-pos[i+1])) 
                 len=pos[i]-abs(pos[i+1]);
    }
    if(pos[i]>=0)
        if(len<(pos[i]+1))
            len=pos[i]+1;

    std::cout << (len+1) << std::endl;
}
int main() {

    int t,n;
    std::cin >> t;
    while(t--)
        func();

    return 0;
}

2)对于测试用例:

  

1 1 1

上面的代码显示 SIGSEGV

3 个答案:

答案 0 :(得分:1)

如果pos的大小为1pos.size()-2不等于-1,则它是size_t的最大值(无符号类型)可以保留在您的系统上。因此循环一直运行到i很大。

有一个最大数量的定义:SIZE_MAX。通常在现代的64位系统18446744073709551615上。

for(i=0;i<=(pos.size()-2);i++)用于pos.size()==1的无限循环,对于i == SIZE_MAX,条件是SIZE_MAX<=SIZE_MAX,这是正确的,然后i绕到{{ 1}},然后继续。

您正在通过访问0来调用未定义的行为。可能是编译器对此进行了优化,因此您可以一次又一次地计数到vector

答案 1 :(得分:1)

正如其他人所提到的,size()的类型为size_t,它是无符号的,因此size() - n可能会为所有非零n下溢。

由于此下溢,循环将至少执行一次。

i等于零且pos.size()等于1的情况下,pos[i+1]的索引是未定义的行为,可能会造成段错误:

else if(len<(pos[i]-pos[i+1])) 
    len=pos[i]-abs(pos[i+1]);

pos是一个向量,因此分配的大小通常会更多,因此i直到与向量的初始分配大小相等时才可能分段。当发生这种情况时,pos[i+1]的索引位于为该向量分配的内存的末尾。

那也有可能甚至不会出现段错误,但是在下一页边界上-一旦您具有未定义的行为,就很难准确地知道程序何时崩溃而不进行调试或添加跟踪输出,而实际上并没有同样重要,因为您应该更正代码。

答案 2 :(得分:0)

size()返回未签名的size_t。当size为1时,大小-2是一个负数,该整数将舍入为一个较大的可能数。因此,您的for循环在不应执行的时间执行。