C++ 在递归函数中释放内存时堆损坏

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];

我正在实现一个算法来选择数组的第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];
    }
    // 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