C语言中使用递归选择排序的分段错误

问题描述 投票:0回答:1

我已经写了一个C程序。它应该使用递归选择排序,但对于大输入(10000 或更多)会出现分段错误。调试器说段错误发生在 findim 函数中,但我几乎不可能找出它发生的原因,因为 findmin 函数也是递归的,我无法想象计算机对 10000 个数字的输入进行的所有操作。

如果你想知道 inputType 是什么,它决定了数组中值的顺序。这些值分别表示有序、几乎有序、逆序、随机。

这就是我写的全部程序。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define DIM_VEC 6
#define MAX_RAND 100

typedef enum {
    ORDINATO, QUASI_ORDINATO, INV_ORDINATO, CASUALE
} inputType;

//Funzione genera_array(…)
int *generaArray(int dimensione, inputType tipo_schema);

void swap(int *a, int *b);

//E2_1: Selection Sort ricorsivo con interi
void selectionSortRec(int A[], int dimA, int start);
int findmin(int A[], int minpos, int start, int dim);



int main() {
    setvbuf(stdout, NULL, _IONBF, 0);
    int ord, dim;
    int *array = NULL;
    int N[DIM_VEC] = {100, 1000, 10000, 100000, 200000, 500000};
    double tempo;
    srand(time(NULL));

    printf("\nScegli l'ordine dell'array "
           "\n0 - ORDINATO, 1 - QUASI_ORDINATO, 2 - INV_ORDINATO, 3 - CASUALE");
    scanf("%d", &ord);
    if(ord < 0 || ord > 3)
        ord = 0;

    printf("\nScegliere la dimensione dell'array ");
    for(int i = 0; i < DIM_VEC; i++) {
        printf("\n%d -- %d", i, N[i]);
    }
    scanf("%d", &dim);
    if(dim < 0 || dim > 5)
        dim = 0;

    array = generaArray(N[dim], ord);

    tempo = clock();
    selectionSortRec(array, N[dim], 0);
    tempo = (clock() - tempo) / CLOCKS_PER_SEC;
    printf("\nTempo impiegato: %lf", tempo);

    free(array);

    return 0;
}

//Funzione genera_array(…)
int *generaArray(int dimensione, inputType tipo_schema) {
    int *a = calloc(dimensione, sizeof(int));
    int j;

    switch (tipo_schema) {
        case ORDINATO:
            for(int i = 0; i < dimensione; i++)
                a[i] = i;
            break;
        case QUASI_ORDINATO:
            for(int i = 0; i < dimensione / 2; i++) {
                a[i] = i;
            }
            for(int i = dimensione /2; i < dimensione; i++) {
                a[i] = rand() % MAX_RAND;
            }
            break;
        case INV_ORDINATO:
            j = dimensione;
            for(int i = 0; i < dimensione; i++) {
                a[i] = j;
                j--;
            }
            break;
        case CASUALE:
            for(int i = 0; i < dimensione; i++) {
                a[i] = rand() % MAX_RAND;
            }
            break;
    }

    return a;

}


//E2_1: Selection Sort ricorsivo con interi
void selectionSortRec(int A[], int dimA, int start) {
    int minIndex;

    if (start >= dimA - 1)
        return;

    minIndex = findmin(A, start, start +1, dimA);


    swap(&A[minIndex], &A[start]);
    selectionSortRec(A, dimA, start+1);
}
int findmin(int A[], int minpos, int start, int dim) {

    if (start == dim)
        return minpos;

    if (A[start] < A[minpos])
        minpos = start;
    return findmin(A, minpos, start + 1, dim);

}

void swap(int *a, int *b) {
    int aux = *a;
    *a = *b;
    *b = aux;
}

我尝试不使用交换函数并验证数组生成函数是否有效,但它们似乎都可以,因为在较小的输入上它们可以工作,并且我尝试打印数组的所有元素并且它可以,但也许我忘记了一些方面。

c recursion segmentation-fault dynamic-memory-allocation selection-sort
1个回答
0
投票

您可以尝试更改堆栈大小,看看是否可以进一步进行递归,但正如其他人警告的那样……最终您会在某个时候用完它。

更改堆栈大小示例如下(在 linux mint 20.x、gcc 9.4.0 上)

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/resource.h>

int main (int argc, char **argv)
{
    struct rlimit stackSz;

    if ( 0 == getrlimit(RLIMIT_STACK, &stackSz) )
    {
        fprintf(stderr, "current: rl.rlim_cur == %lu rl.rlim_max == %lu\n", stackSz.rlim_cur, stackSz.rlim_max );

        stackSz.rlim_cur *= 2; // double stack size - for example ....
        setrlimit(RLIMIT_STACK, &stackSz);
        if (0 != setrlimit(RLIMIT_STACK, &stackSz) )
           fprintf(stderr, "ERROR: setrlimit error = %s\n", strerror(errno) );
        else
           fprintf(stderr, "updated: rl.rlim_cur == %lu rl.rlim_max == %lu\n", stackSz.rlim_cur, stackSz.rlim_max );
    }
    else
       fprintf(stderr, "ERROR: getrlimit error = %s\n", strerror(errno) );

    return 0;
}

./rlimit 
current: rl.rlim_cur == 8388608 rl.rlim_max == 18446744073709551615
updated: rl.rlim_cur == 16777216 rl.rlim_max == 18446744073709551615
© www.soinside.com 2019 - 2024. All rights reserved.