简体   繁体   中英

why does using '<=' instead of '<' in the loop condition gives a segmentation fault [SIGSEGV]?

I was solving a problem on codechef in the DECEMBER contest - https://www.codechef.com/DEC19B/problems/BINADD . Somewhere in the code I put this loop:

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

Here pos is a vector declared as: vector<int> pos;

For these values the code shows a SIGSEGV:

size of pos = 1, pos[0]=0, len=0

But if I replace i<=(pos.size()-2) with i<(pos.size()-1) in the loop there occurs NO SIGSEGV. Does anyone have an explanation

NOTE: 1) Full code:

#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) For the test case:

1 1 1

The above code shows SIGSEGV .

If the size of pos is 1 , pos.size()-2 is not equal to -1 , it is the maximum value which a size_t (which is an unsigned type) can hold on your system. So the loop runs till i is a very very large number.

There is a define for the maximum number: SIZE_MAX . It is usually on modern 64bit systems 18446744073709551615 .

for(i=0;i<=(pos.size()-2);i++) is for pos.size()==1 an endless loop, for i == SIZE_MAX , the condition is SIZE_MAX<=SIZE_MAX , which is true and then i wrap around to 0 and so it goes on.

You are invoking undefined behavior by accessing the vector out of bounds. Probably the compiler optimises this away and so you simply count to SIZE_MAX again and again.

As the others have mentioned, size() is of type size_t which is unsigned, so size() - n potentially underflows for all non-zero n .

Because of this underflow, the loop will execute at least once.

With i equal to zero and pos.size() equal to 1, the indexing of pos[i+1] is undefined behaviour which may segfault:

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

pos is a vector so often there will be more allocated that the size, so it might not segfault until i grows to be equal to the initial allocation size of the vector; when this happens the indexing of pos[i+1] is off the end of the memory allocated for the vector.

It's also possible it doesn't even segfault then, but at the next page boundary - once you have undefined behaviour then it's hard to tell exactly when a program crashes without debugging it or adding trace output, and it really doesn't matter that much either, as you should correct the code instead.

size() returns an unsigned size_t . When size is 1, size -2 is a negative number which wraps round to a large posisibe number. Your for loop therefore executes when it shouldn't.

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