C ++中的随机段错误

时间:2009-08-22 21:49:39

标签: c++ segmentation-fault

我是C ++的新手,我不知道从哪里开始,所以我将代码上传到pastebin,因为它有很多。

即使使用gcc的-Wall选项,此代码编译也很好,并且不会发出警告。

它应该生成所有素数,直到作为命令行参数给出的数字。

在较小的数字(例如4,000或5,000)上,它可以正常工作。在4,000,000这样的较大数字上,几乎所有时间都会出现段错误。在两者之间的数字上,无论是否运行都会受到影响。

7 个答案:

答案 0 :(得分:10)

int primes[max];

prime = primes;
while(*prime) {
    *prime = 0;
    prime++;    
}

在前面的代码中,您可以轻松地在内存中随机运行,实际上您将通过RAM直到找到0.如果您的数组中没有0,那么它将运行到不属于该内存的内存中过程和段错误将会发生。

编辑:正如爱尔康指出的那样,你也在代码中的其他地方这样做。

最好不要在堆栈上分配素数,因为你不太可能拥有那么多堆栈内存。

要解决此问题,请尝试使用以下代码

int primes = new int[max];

size_t count = 0;
while( count < max ) 
{
    prime[count] = 0;
    count++;    
}

不要忘记调用delete [] primes;在代码的最后(当你完成素数数组时)

答案 1 :(得分:1)

您正在堆栈上分配数组。堆栈的大小有限,可能会溢出。

尝试使用new / delete分配数组。

答案 2 :(得分:1)

一方面,这是有问题的:

int sum_array(int num_array[]) {
    int current_total = 0;
    int *iptr = num_array;
    while(*iptr) {
        current_total += *iptr;
        iptr++;
    }
    return current_total;
}

这说的是从你给出的数组的开头开始。虽然内存块中的值int的大小不为零,但移动到下一个内存块。这里发生的事情是它会继续超过你的数组的末尾,最终搞乱内存它不应该是导致段错误的原因。它似乎是随机的原因是有时候数组末尾的内存是空的,这样就行了。但有时它不是,然后它访问内存它不应该和CRASH。

这可能不是唯一的问题,但它是我注意到的第一个问题。要修复它,请跟踪数组的大小,将其传递给函数,然后使用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循环的结束。

其他人建议从堆而不是堆栈中分配数组。这对于一个巨大的阵列来说是一个好主意,但是,根据我的经验,至少堆栈溢出通常不会导致段错误。编译器通常会注意到分配的空间多于堆栈中的空间。我仍然建议使用一个向量(在你的作业中获得额外的功劳,看看你是否可以找到如何使用从堆中指定的指针数组分配的双指针来实现自己的向量;)或者只使用std: :向量。它是一个可扩展的数组,可以让你在找到它们时为你的数组添加素数而不是分配你不一定需要的整个空间。

答案 3 :(得分:1)

您应该动态分配素数数组primes,即:

int* primes = new int[max];

你的程序甚至不应该按原样编译。祝你的作业好运!

答案 4 :(得分:1)

其他人(例如Goz)提供了正确答案 - 未初始化变量的值不能依赖,因为它们在不同的运行中不同。正如其他人所指出的那样,在堆栈上分配大型数组也存在风险,因为堆栈空间通常比堆空间更稀缺。

作为一个副作用,以primes[max]的方式分配可变大小的数组不是符合标准的C ++,而是g ++扩展,因此您的代码不可能与其他代码一起使用编译器。您可以使用newdelete代替 - 但在这些情况下养成使用vector<int>的习惯会更好,因为它会为您进行清理。

[编辑:感谢威尔指出问题的根本原因在于其他地方。]

答案 5 :(得分:1)

Goz已经指出早期的事情是如何开始出错的。

初学者容易犯错误,但即使是退伍军人也会犯同样的错误。出于这个原因,退伍军人已经制作了出色的程序来自动发现问题:

免费程序包括lint,它会在您运行代码之前对其进行检查,并且 - 甚至更好 - valgrind会在您运行代码时检查代码!在Windows上,还有其他商业选择,例如Purify

通过valgrind和静态代码检查器在开发过程中运行程序,以及编译器启用的所有警告编译,即使对于经验丰富的退伍军人也是开发卫生的一部分。

答案 6 :(得分:0)

int primes[max];

在堆栈中分配大型数组是不好的,因为默认情况下,堆栈的大小很小。最好在堆中分配primes []。