为什么在环路条件中使用'<='而不是'<'会产生分段错误 [SIGSEGV]?
why does using '<=' instead of '<' in the loop condition gives a segmentation fault [SIGSEGV]?
我在 12 月的比赛中解决了 codechef 的问题 - https://www.codechef.com/DEC19B/problems/BINADD .在代码中的某个地方,我放了这个循环:
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()-1)
替换i<=(pos.size()-2)
,则不会发生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(对于测试用例:
11 1
上面的代码显示了SIGSEGV。
正如其他人所提到的,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]
的索引将脱离为向量分配的内存的末尾。
也有可能它甚至没有段错误,但在下一页边界 - 一旦你有未定义的行为,那么很难准确地判断程序何时崩溃而不调试它或添加跟踪输出,而且它真的没有那么重要,因为你应该纠正代码。
如果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
绕到0
,就这样继续下去。
您通过越界访问vector
来调用未定义的行为。编译器可能对此进行了优化,因此您只需一次又一次地计数SIZE_MAX
。
size()
返回一个无符号的size_t
。当大小为 1 时,大小 -2 是一个负数,它四舍五入为一个大的 posisibe 数。因此,您的 for 循环会在不应该执行时执行。
- 分段故障(堆芯转储)矢量
- 数组的指针从不分段故障
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 在线编译器中的分段C++没有打印消息
- 呼叫运营商<<临时
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- Windows 10-使用gtkmm-3.0库和g++[包括再现]的分段故障
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 如何防止clang格式在流运算符调用之间添加换行符<<
- 尝试使用集合函数时出现分段错误
- <<操作员在下面的行中工作
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)