C++ 在递归函数中释放内存时堆损坏
我正在实现一个算法来选择数组的第k个最小元素。到目前为止,当我试图释放堆内存时,我得到了一个错误:crt检测到应用程序在堆缓冲区结束后写入内存C++ 在递归函数中释放内存时堆损坏,c++,pointers,heap-corruption,C++,Pointers,Heap Corruption,我正在实现一个算法来选择数组的第k个最小元素。到目前为止,当我试图释放堆内存时,我得到了一个错误:crt检测到应用程序在堆缓冲区结束后写入内存 int SEQUENTIAL_SELECT(int *S , int k , int n) { if(n<=Q) // sort S and return the kth element directly { qsort(S,n,sizeof(int),compare); return S[k];
int SEQUENTIAL_SELECT(int *S , int k , int n)
{
if(n<=Q) // sort S and return the kth element directly
{
qsort(S,n,sizeof(int),compare);
return S[k];
}
// subdivide S into n/Q subsequences of Q elements each
int countSets = ceil((float)n/(float)Q);
//sort each subsequnce and determine its median
int *medians = new int[countSets];
for(int i=0;i<countSets;i++)
{
if(i==countSets-1)
{
int size = Q - (n%Q);
qsort(&S[Q*i],size,sizeof(int),compare);
medians[i] = S[i*Q+size/2];
continue;
}
qsort(&S[Q*i],Q,sizeof(int),compare);
medians[i] = S[i*Q+Q/2];
}
// call SEQUENTIAL_SELECT recursively to find median of medians
int m = SEQUENTIAL_SELECT(medians,countSets/2,countSets);
delete[] medians;
int size = (3*n)/4;
int* s1 = new int[size]; // contains values less than m
int* s3 = new int[size]; // contains values graten than m
for(int i=0;i<size;i++)
{
s1[i] = INT_MAX;
s3[i] = INT_MAX;
}
int i1=0;
int i2=0;
int i3=0;
for(int i=0;i<n;i++)
{
if(S[i]>m)
s3[i3++] = S[i];
else if(S[i]<m)
s1[i1++] = S[i];
else
i2++; // count number of values equal to m
}
if( i1>=k )
m = SEQUENTIAL_SELECT(s1,k,i1);
else if( i1+i2+i3 >= k)
m = SEQUENTIAL_SELECT(s3,k-i1-i2,i3);
delete[] s3;
delete[] s1;
return m;
}
@Dcoder肯定是正确的,Q-n%Q是不正确的。应为n%Q。此外,计算大小=3*n/4不可靠;试着用n=6,假设Q实际上是5,给定向量[1,2,3,4,5,0] 通过简单地检查每个数组下标赋值处的索引值,可以避免大量的眼睛盯着代码看,尽管这不会捕获qsort中的赋值,但下面将对此进行详细介绍 你一定会想到,你正在使用大量的内存来执行一个简单的操作,而这个操作实际上是可以就地完成的。通常,避免执行就地操作的原因是您需要保留原始向量,但您正在使用qsort计算中间值,该中间值在就地排序,因此原始向量已被修改。如果这是可以接受的,那么就没有理由不执行中间值算法的其余部分。[1] 顺便说一句,虽然我当然不是那种害怕浮点计算的人,但countSets=ceilfloatn/floatQ完全没有理由。n+Q-1/Q可以正常工作。这个习惯用法也可以用于计算大小,尽管我根本不确定3n/4计算是从哪里来的
[注1]提示:与其连续分组,不如将向量分为五个区域,并找到每个区域第i个元素的中值。找到后,将其与第一个区域的第i个元素交换;一旦这样做了,你的第一个区域——向量的前五分之一——包含中间值,你可以在这个子向量上递归。这意味着实际上要将中值代码作为一系列比较来编写,这很乏味,但比调用qsort要快得多。这也避免了我上面提到的退化情况,即中值计算错误地返回向量中的最小元素。错误发生在哪里?尝试在valgrind或类似的内存调试器中运行应用程序。为什么要使用新的int[]而不是std::vector?编辑:行int size=Q-n%Q;看起来不正确。我想在CUDA程序中使用此函数,但不幸的是,您不能在CUDA内核中使用std::vector。对不起,这段代码与CUDA有什么关系?valgrind是一个Linux工具,我使用的是vs2010