在堆栈末尾进行分配的递归函数

Recursive function that allocates at the end of the stack

本文关键字:分配 递归函数 堆栈      更新时间:2023-10-16

好吧,我遇到了一个奇怪的问题。我正在实现一种算法,叫做埃拉托申斯筛。我有一个函数primeArray_r,它递归地处理我生成的数组,然后当它到达末尾时,它在堆上创建一个新数组,然后在堆栈中向下下降时开始填充它,最后将指针返回到数组的开头。如果你想知道我为什么直接增加指针,这是赋值的要求。我在运行时遇到问题,但这取决于我使用的环境。在Windows中,它似乎会毫无征兆地爆炸,有时还会重复完全相同的序列。在Ubuntu Linux中,这很奇怪。它更稳定一点,如果它工作一次,它将在同一个输入上工作多次,但它会根据输入而失败。例如,我在裸机Ubuntu 14.04 64位上的安装,如果上限为5、9、13、17…或任何数字(N*4)+1,程序就会崩溃,而在我的虚拟安装Lubuntu 13.10 32位上,如果上限是2、4、6、8…或任何数目的N*2,程序就会失败。错误消息基本相同:

Program5.1: malloc.c:2372: sysmalloc: Assertion `(old_top == (((mbinptr) (((char *) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size) >= (unsigned long)((((__builtin_offsetof (struct malloc_chunk, fd_nextsize))+((2 *(sizeof(size_t))) - 1)) & ~((2 *(sizeof(size_t))) - 1))) && ((old_top)->size & 0x1) && ((unsigned long) old_end & pagemask) == 0)' failed.
Aborted (core dumped)

唯一的区别是行号,Lubuntu 13.10中的malloc.c.2369和Ubuntu 14.04中的2372似乎是我在第116行的内存分配过程中造成了某种崩溃:primeArray = new int[primeCount];

我想知道这是否是我的错误,或者我是否发现了在递归堆栈末尾分配内存时暴露的一些错误

#include<iostream>
#include <math.h>
using namespace std;
int* makeArray(int);
int firstZero (int*);
void circleCross(int*, int*, int);
void circleAll(int*, int*);
int* primeArray(int*, int*, int&, int);
int* primeArray_r(int*, int*, int*, int&, int);
int main(){
    //display a title
    cout << "The Sieve of Eratosthenes" << endl;
    cout << "gives you all the primes you want!" << endl;
    cout << "(in the range you specify...)" << endl;
    //ask the user to specify a range of positive numbers
    char repeat;
    int low;
    int high;
    int size;
    do{
        do{
            low = 0;
            high = 0;
            while (low < 1){
                cout << "Give me the lower bound" << endl;
                cin >> low;
            }
            while (high < 1){
                cout << "Give me the upper bound" << endl;
                cin >> high;
            }
        }while (low > high);
        size = high + 1;
        int* array = makeArray(size);
        int *end = array + size;
        int ix;
        double root = sqrt(high);
        do{
            ix = firstZero(array);
            if (ix <= root)
                circleCross(array, end, ix);
        }while ( ix < root);
        circleAll(array, end);
        array += low;
        cout << "Found all the primes!" << endl;
        int primeCount = 0;
        int* arrayPrime = primeArray(array, end, primeCount, low);
        cout << "Here's your primes!" << endl;
        int *primeEnd = arrayPrime + primeCount;
        while(arrayPrime < primeEnd){
            cout << *arrayPrime << endl;
            ++arrayPrime;
        }
        cout << "Enter 'y' to go or any other character to stop" << endl;
        cin >>  repeat;
    } while(repeat == 'y');
    return 0;
}
int* makeArray( int size){
    int *array;
    array = new int[size];
    int *firstAddress = array;
    *array = -1;
    *(++array) = -1;
    int *end = firstAddress + size;
    while (array < end){*(++array) = 0;}
    return firstAddress;
}
int firstZero ( int* array){
    int *ix;
    for (ix = array; (*ix); ++ix);
    int zero = ix - array;
    return zero;
}
void circleCross( int* array, int *end, int factor){
    array += factor;
    *array = 1;
    array += factor;
    while(array < end){
        *array = -1;
        array += factor;
    }
}
void circleAll( int* array, int *end){
    while (array < end){
        if (*array==0)
            *array=1;
        ++array;
    }
}
int* primeArray( int* array, int *end, int &primeCount, int low){
    primeCount=0;
    int *beginning = array;
    int *primeArray = primeArray_r(array, beginning, end, primeCount, low);
    return primeArray;
}
int* primeArray_r(int * array, int * beginning, int *end, int &primeCount, int low){
    int *primeArray;
    if (array == end){
        primeArray = new int[primeCount];
        primeArray += primeCount;
    }
    else{
        if (*array == 1){
            int position = primeCount; 
            ++primeCount;
            primeArray = primeArray_r((array+1), beginning, end, primeCount, low);
            --primeArray;
            *primeArray = array - beginning + low;
        }
        else{
            primeArray = primeArray_r((array+1), beginning, end, primeCount, low);
        }
    }
    return primeArray;
}

在makeArray()中,在数组(while (array < end){*(++array) = 0;})后面写一个0,这会创建未定义的行为。因此,这很可能是导致崩溃的原因,因为这也与分配内存有关。