我是 C++ 新手,不知道从哪里开始,所以我将代码上传到了一个pastebin,因为它有很多。
这段代码编译得很好,并且不会发出警告,即使使用 gcc 的 -Wall 选项也是如此。
它应该生成所有素数,直到作为命令行参数给出的数字。
对于较小的数字(例如 4,000 或 5,000),它可以正常工作。在更大的数字上,例如 4,000,000,它几乎总是因段错误而崩溃。在介于两者之间的数字上,它是否运行会受到影响。
我是 C++ 新手,不知道从哪里开始,所以我将代码上传到了一个pastebin,因为它有很多。
这段代码编译得很好,并且不会发出警告,即使使用 gcc 的 -Wall 选项也是如此。
它应该生成所有素数,直到作为命令行参数给出的数字。
对于较小的数字(例如 4,000 或 5,000),它可以正常工作。在更大的数字上,例如 4,000,000,它几乎总是因段错误而崩溃。在介于两者之间的数字上,它是否运行会受到影响。
int primes[max];
prime = primes;
while(*prime) {
*prime = 0;
prime++;
}
在前面的代码中,您可以轻松地在内存中随机运行,本质上您正在遍历 RAM,直到找到 0。如果您的数组中没有 0,那么它将运行到不属于进程的内存中,并且会发生段错误。
编辑:正如 Alcon 所指出的,您也在代码的其他地方执行此操作。
最好不要在堆栈上分配素数,因为您不太可能有那么多可用的堆栈内存。
要解决此问题,请尝试以下代码
int primes = new int[max];
size_t count = 0;
while( count < max )
{
prime[count] = 0;
count++;
}
并且不要忘记调用 delete[] primes;在代码的末尾(当您完成素数数组时)
您正在堆栈上分配数组。堆栈大小有限,可能会溢出。
尝试使用 new/delete 分配您的阵列。
一方面,这是有问题的:
int sum_array(int num_array[]) {
int current_total = 0;
int *iptr = num_array;
while(*iptr) {
current_total += *iptr;
iptr++;
}
return current_total;
}
这说的是从给定数组的开头开始。当 int 大小的内存块中的值不为零时,移动到下一个内存块。这里发生的事情是它会继续超过你的数组的末尾,最终弄乱它不应该的内存,这就是导致段错误的原因。看起来随机的原因是有时数组末尾的内存是空的,这会正常工作。但有时它不是,然后它访问不应该访问的内存并崩溃。
这可能不是唯一的问题,但这是我注意到的第一个问题。要修复它,请跟踪数组的大小,将其传递给函数,然后使用 for 循环迭代它而不是使用指针。像这样:
int sum_array(int num_array[], int arraySize) {
int current_total = 0;
for(int i = 0; i < arraySize; i++) {
current_total += num_array[i];
}
return current_total;
}
我再看看有没有别的。
编辑:
再看一遍,你在另外两个地方做同样的事情。这里:
while(*prime) {
cout << *prime << " ";
prime++;
}
和这里:
while(*prime) {
*prime = 0;
prime++;
}
在这两个地方,我都将美元赌在甜甜圈上,您超出了您的阵列,这就是导致段错误的原因。如果您是新手,我强烈建议您不要使用指针算法来遍历您的数组。坚持使用旧的 for 循环并跟踪 for 循环的结束。
其他人建议从堆而不是堆栈分配数组。这对于一个巨大的数组来说是个好主意,但是,至少根据我的经验,堆栈溢出通常不会导致段错误。当您分配的空间多于堆栈中的空间时,编译器通常会注意到。我仍然建议使用向量(对于你的家庭作业有很大的额外功劳,看看你是否可以弄清楚如何使用从堆中分配为指针数组的双指针来实现你自己的向量;)或者只使用标准: :向量。这是一个可扩展的数组,它可以让您在找到它们时将素数添加到数组中,而不是分配一吨您不一定需要的空间。
您应该动态分配素数数组primes
,即:
int* primes = new int[max];
您的程序甚至不应该按原样编译。祝你的家庭作业好运!
其他人(例如 Goz)提供了正确的答案——未初始化变量的值不能被依赖,因为它们在每次运行中都不同。正如其他人指出的那样,在堆栈上分配大型数组也是有风险的,因为堆栈空间通常比堆空间更稀缺。
作为一个附带问题,以您使用的方式分配可变大小的数组primes[max]
不是符合标准的 C++,而是 g++ 扩展,因此您的代码不太可能与其他编译器一起使用。您可以使用new
anddelete
来代替 - 但最好养成vector<int>
在这些情况下使用的习惯,因为它会为您完成清理工作。
[编辑:感谢威尔指出麻烦的真正根源在其他地方。]
int primes[max];
在堆栈中分配巨大的数组是不好的,因为默认情况下,堆栈的大小很小。最好在堆中分配 primes[]。