循环时出现分段故障
Segfault while looping
处理一个简单的问题,但由于程序的写入超过了数组的末尾而导致分段错误。
#include <iostream>
#include <stdio.h>
static const int N = 46350;
int main()
{
int* intarray = new int[N];
for (int i = 2; i < N; ++i)
{
intarray[i] = 1;
}
for (int i = 2; i < N; ++i)
{
if (intarray[i])
{
for (int j = i; j*i < N; ++j)
{
printf("before i: %i j: %i ", i, j);
std::cout << "a: " << intarray + i*j << std::endl;
intarray[i*j] = 0;
printf("after i: %i j: %i ", i, j);
std::cout << "a: " << intarray + i*j << std::endl;
}
}
}
delete [] intarray;
return 0;
}
控制台输出:
before i: 211 j: 219 array: 0x21dd24c
after i: 211 j: 219 array: 0x21dd24c
before i: 46349 j: 46349 array: 0x2488aec
对于N=46349,这种情况不会发生。不确定发生了什么。
整数溢出导致了这种情况。i
和j
的乘积溢出了类型int
的范围并产生负值,这显然被比作"小于N
"。稍后,您尝试在负索引i * j
处修改内存,这将导致不可预测的结果。事实上,溢出本身已经在产生未定义的行为。
对于N
的这个值,您可以使用unsigned int
类型而不是int
类型。前者的正范围是前者的两倍。但在一般情况下,你必须记住,两个int
值的乘积不一定适合int
类型的范围。
在您的情况下,i
可能会变得与46349
一样大,并且46349*46349=21848322500,这大于有符号2补32位整数2147483647的典型上限。
N=463549的版本也以同样的方式被正式破解,只是你很幸运有了那个版本。if (intarray[i])
检查可防止内部循环在可能导致溢出的情况下运行。
在您的案例中,最大整数(int
(是2^31-1
,即2147483647
。这个数字的平方根是46340.95...
,所以当你乘以i * j
时,你得到了一个整数溢出,结果看起来是负的,它看起来是< N
,并且在循环中被允许通过。所以你有错。所以说真的,任何高于46340
的东西,你都可能会遇到一些问题。
相关文章:
- 分段故障(堆芯转储)矢量
- 数组的指针从不分段故障
- Windows 10-使用gtkmm-3.0库和g++[包括再现]的分段故障
- 分段故障 运行C++代码时出现 SIGSEGV
- 分段故障背包问题
- 分段故障 11,从类函数显示动态 C 字符串
- 面临分段故障 使用 ffmpeg 读取视频时,因为"pFormatCtx-> streams [i]-> codecpar"的地址0x00
- 在C++中,当指向删除和指向不同对象时,分段故障指针
- 分段故障说明
- 分段故障(核心转储)-不知道为什么
- 分段故障线程
- hiredis SET遇到分段故障
- 分段故障,合并排序算法
- 多线程程序中的分段故障和gdb回溯上的不完整信息
- 到达主C++之前分段故障
- 分段故障核心使用 IF流转储
- 使用向量的移动键盘排列(分段故障)
- 在二进制树插入和遍历期间,我得到了分段故障
- 分段故障在类之间返回整数
- C++分段故障BST