我正在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 。
答案 0 :(得分:1)
如果pos
的大小为1
,pos.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循环在不应执行的时间执行。