递归合并排序,大数组的分段错误
recursive merge sort, segmentation fault for big arrays
我已经递归地实现了合并排序。它可以工作到一定大小的排序数组,然后以"分段错误"崩溃。在Intel Xeon 16GB的情况下,最大浮点数组大小为17352,int数组更大,double数组更低。在AMD A10,16GB,浮动的限制是2068。显然存在内存问题。我为数组(非递归)所做的其他排序算法可以很好地处理~2e6。编译器为GCC 4.4.7。如何改进这种合并排序,使其适用于较大的数组?
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <vector>
using namespace std;
// --------------------------------------------------------
// merge 2 subarrays of 1 array around its middle im
template <class C>
void merge(C* arr, int ilow, int imid, int ihigh)
{
vector<C> temp; // array seg faults earlier than vector
for(int i=ilow; i<=ihigh; i++) temp.push_back(arr[i]); // copy array
int i1=ilow, i2=imid+1, ai=ilow; // starting positions
while(i1<=imid && i2<=ihigh) // compare 1st and 2nd halves
{
if(temp[i1]<=arr[i2])
{
arr[ai] = temp[i1];
i1++; // leave smaller val behind
}
else
{
arr[ai] = temp[i2];
i2++; // leave smaller val behind
}
ai++; // move forward
}
if(i2>ihigh) while(i1<=imid) // if 2nd is done, copy the rest from 1st
{
arr[ai] = temp[i1];
i1++;
ai++;
}
if(i1>imid) while(i2<=ihigh) // if 1st is done, copy the rest from 2nd
{
arr[ai] = temp[i2];
i2++;
ai++;
}
} // merge()
// --------------------------------------------------------
// merge sort algorithm for arrays
template <class C>
void sort_merge(C* arr, int ilow, int ihigh)
{
if(ilow < ihigh)
{
int imid = (ilow+ihigh)/2; // get middle point
sort_merge(arr, ilow, imid); // do 1st half
sort_merge(arr, imid+1, ihigh); // do 2nd half
merge(arr, ilow, imid, ihigh); // merge 1st and 2nd halves
}
return;
} // sort_merge()
///////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
// crashes at 17353 on Intel Xeon, and at 2069 on AMD A10, both 16Gb of ram
const int N=17352+0;
float arr[N]; // with arr[double] crashes sooner, with arr[int] crashes later
// fill array
for(long int i=0; i<N; i++)
{
//arr[i] = rand()*1.0/RAND_MAX; // random
arr[i] = sin(i*10)+cos(i*10); // partially sorted
//arr[i] = i; // sorted
//arr[i] = -i; // reversed
}
sort_merge(arr, 0, N-1);
return 0;
}
考虑复制数组的方式:
vector<C> temp; // array seg faults earlier than vector
for(int i=ilow; i<=ihigh; i++) temp.push_back(arr[i]); // copy array
完成此操作后,temp
包含ihigh - ilow + 1
值,这些值可从temp[0]
到temp[ihigh - ilow]
访问。这意味着temp
中的所有值与arr
相比偏移了-ilow
。
但是,代码的其余部分使用源数组的索引访问temp
,例如:
if(temp[i1]<=arr[i2]) // i1 isn't a valid index into temp, should be (i1 - ilow)
因此发生了坠机事件。在temp
中使用适当的偏移量时,您的代码似乎工作正常。
由于臭名昭著的堆栈溢出,如果N
足够大,以下内容本身就足以导致分段错误。如果没有,则应填充数组。
int main(int argc, char *argv[])
{
// crashes at 17353 on Intel Xeon, and at 2069 on AMD A10, both 16Gb of ram
const int N=17352+0;
float arr[N];
}
原因是局部变量倾向于在堆栈上分配,但堆栈的大小有限,并且不是为大规模内存分配而设计的。如果你改为
float *arr = new arr[N]; // probably should be unique_ptr instead....
或
std::vector<float> arr(N);
您不会有任何问题,因为这两种方法都在堆上分配内存。
相关文章:
- 在某些循环内使用vector.push_back时出现分段错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 当我的阵列太大时出现分段错误
- 分段错误当我试图运行程序时出错
- 在c++中初始化矩阵时出现分段错误(核心转储)
- 尝试使用集合函数时出现分段错误
- 我无法缩小此分段错误的原因
- g++的分段错误(在NaN上使用to_string两次时)
- 我是如何在这段代码中出现分段错误的
- 创建结构的数组时遇到分段错误
- 在c++中键入向量中的所有值后,得到分段错误(核心转储)
- 在 c++ 中实现 Trie 时出现分段错误
- 为什么 fstream 在打开带有格式的文件时会导致分段错误?
- 为什么我遇到分段错误?
- 动态类的分段错误(家庭作业问题)
- 分段错误 - 读取初始化指针的数组
- 如何摆脱C ++中的分段错误错误?
- 使用 CTYPE 时出现分段错误
- 为什么代码给出分段错误?