插入排序导致分段错误:缩放后11

时间:2011-11-22 20:46:41

标签: c++ syntax

我写了一个简单的插入排序实现来试图破坏生锈,并开始我希望通常更好地理解algortihms。该文件包含2000万个随机数。代码如下:

#include <fstream>
#include <time.h>
#include <cstdlib>

using namespace std;

void insertionSort(double numbers[], int array_size);

int main() {
    int count;
    double twentyMMNumbers[20000000];
    ifstream inputFile;
    time_t now;
    time(&now);

    inputFile.open("20KRandomsNumbers.data");       //Opens input file
    if(inputFile.fail())
    {
        printf("Cannot open inputFile");
        exit(1);
    }

    count = 0;
    printf("%d\n",count);
    inputFile >> twentyMMNumbers[count];
    printf("%f\n",twentyMMNumbers[count]);
    while(inputFile)
    {   //While loop
        count++;
        if(count < 20000000)
            inputFile >> twentyMMNumbers[count];
    }
    inputFile.close();  

    printf("%s\n", ctime(&now));    //BEFORE
    insertionSort(twentyMMNumbers, 20000000); //Insertion Sort 20KRandomNumbers
    printf("%s\n", ctime(&now)); //AFTER
    for(int i = 0; i < count; i++)
        printf("%f\n",twentyMMNumbers[i]);  
}

void insertionSort(double numbers[], int array_size)
{
  int i, j, index;
  for (i=1; i < array_size; i++)
  {
    index = numbers[i];
    j = i;
    while ((j > 0) && (numbers[j-1] > index))
    {
      numbers[j] = numbers[j-1];
      j = j - 1;
    }
    numbers[j] = index;
  }
}

当代码只有20,000个条目时,代码工作正常,但现在给了我:

Segmentation fault: 11

这是由于我增加了数组的大小吗? 如果您有任何关于优化此功能的提示,请随时指出。

3 个答案:

答案 0 :(得分:2)

讽刺的是(给定这个站点名称),你有一个堆栈溢出。您需要在堆上动态分配那么多内存。

为了更清晰,这一行:

double twentyMMNumbers[20000000];

需要

double* twentyMMNumbers = (double*)malloc(20000000*sizeof(double));

当然,在退出程序之前,您需要释放内存(作为最佳做法):

free(twentyMMNumbers);

答案 1 :(得分:2)

它适用于较小的数组大小,所以这里有一些注释(因为它在CodeReview上)和一些更大的数组大小的修复。

1,如果要使用固定大小的数组,请使用常量而不是200000(或20000000)文字。

2,使用动态数组更好。在读完第一行后分配内存,并使用readed大小作为新数组的大小。此外,我会将数据文件的大小(文件的第一行)存储在一个单独的变量中,而不是存储在数组中。

int dataSize;
inputFile >> dataSize;
double *twentyMMNumbers = new double[dataSize];

它分配确切的内存量。不多也不少。

它还修复了 Segmentation fault 错误。有关更多信息,请查看以下问题:Segmentation fault on large array sizes

(不要忘记使用delete[]取消分配数组。)

3,如果记录的数量多于数组的大小,则无需读取整个文件。我修改了while循环:

while (inputFile) {   
    if (count >= dataSize) {

        break;
    }
    inputFile >> twentyMMNumbers[count];
    count++;
}
inputFile.close();  

也许exit(-1)和错误消息会更好,而不是break

4,以下评论是不必要的:

//While loop

5,你应该将数组的实际大小传递给insertionSort函数,所以写下:

insertionSort(twentyMMNumbers, dataSize); 

此处的评论也是不必要的。

6,改进错误处理:dataSize的值大于文件中的数字时会发生什么?

7,我会使用最后一个printArray循环和一个for函数提取readInput函数。

8,考虑使用C ++样式打印而不是printf s:

cout << "Hello world!" << endl;

#include <iostream>是必需的。)

答案 2 :(得分:1)

你的while循环中有问题:

while(inputFile)
{   //While loop
    count++;
    if(count < 20000000)
        inputFile >> twentyMMNumbers[count];
}

仅当文件包含&lt; = 20000000个数字时,此循环才会终止。如果count变为20000000,它将不再尝试从inputFile读取,但仍然使用inputFile作为继续循环的条件。然后当count达到最大int值时,它会回绕,你将使用负数索引twentyMMNumbers。这很可能是您遇到分段错误的原因。

20000000是代码中的“神奇数字”。

,而不是在文件开头都有const int NumElements = 20000000的地方写下来