Segmentation fault

di il
7 risposte

Segmentation fault

Ciao a tutti!

Vi chiedo gentilmente se potreste aiutarmi con un programmino con il quale sto avendo problemi. Vi copio testo e la mia soluzione (non funzionante ovviamente).

Usando le definizioni di tipo fornite nell’esercizio precedente, implementare la funzione ricorsiva C:
• int* maggioriDi(TipoSCL scl, int m, int* n)
che, presi in input una SCL scl, un valore intero m ed un puntatore n ad intero, restituisce un array
di interi contente gli elementi della SCL che hanno valore maggiore (strettamente) di m ed assegna alla
variabile puntata da n il numero di tali valori (cio`e la dimensione dell’array restituito). L’ordine degli
elementi nell’array restituito deve rispettare quello nella SCL. Si possono definire funzioni ausiliarie
purch ´e ricorsive

Mia soluzione:

#include <stdio.h>
#include <stdlib.h>
#include "esercizio.h"


int*  maggioriDi(TipoSCL scl, int m, int* n){
	TipoSCL testa=scl;
	int b =conta(scl,m);
	if (b==0) {
		*(n)=0;
		return NULL;
	}
	*(n)=0;
	int*array=(int*) malloc(sizeof(int)*b);
	controlla(testa,m,array,n);
return array;
}
		


int conta (TipoSCL scl, int m) {
	if (scl!=NULL) {
		if (scl->info>m) {
			scl=scl->next;
			return 1+conta (scl,m);
		}	
		scl=scl->next;
		conta(scl,m);
	}
	return 0;
}



void controlla (TipoSCL scl,int m,int*ris,int *a) {
	if (scl==NULL) {
		return ;
	}	
	else {
		if (scl->info>m) {
			ris[*(a)]=scl->info;
			*(a)++;
			scl=scl->next;
			controlla(scl,m,ris,a);
		}
		scl=scl->next;
		controlla(scl,m,ris,a);
		
	}
}
		
	

Facendo vari test scopro che la parte incriminante è nella funzione controlla. Non capisco perchè quando scl prende il valore NULL (alla fine della lista) la funzione mi salta la condizione if (scl==NULL) { e mi causa un segmentation fault.

Grazie in anticipo a chi mi aiuterà!

7 Risposte

  • Re: Segmentation fault

    Ciao come da regolamento ti invito a modificare il titolo della discussione in modo da renderlo più specifico.
  • Re: Segmentation fault

    Il problema è dovuto dal fatto che non chiudi tutte le chiamate ricorsive.
    Ho scritto la funzione un po' meglio e dovrebbe funzionare
    void controlla (TipoSCL scl, int m, int *ris, int *a) {
        if (scl == NULL) {
            return ;
        } else {
            if (scl->info > m) {
                ris[*(a)++]=scl->info;
                controlla(scl->next, m, ris, a);
                return;
            }
            controlla(scl->next, m, ris, a);
            return;
        }
    }
    
    Fammi sapere se funziona e se non ti è chiaro qualcosa
  • Re: Segmentation fault

    Ciao! Grazie per la disponibilità prima di tutto! Ho provato a fare come dici ma il problema non si risolve. Non capisco perchè nel modo in cui avevo scritto io la funzione non dovrebbe bloccarsi... la chiamata ricorsiva non si chiude quando scl==NULL?
  • Re: Segmentation fault

    Una funzione ricorsiva richiama se stessa infinite volte quindi il return come lo hai scritto tu esce solo dall'ultima chiamata, ma poi il programma si trova nella chiamata precedente, quindi con il return come te l'ho modificato pian piano chiudi tutte le ricorsioni e esci. Il fatto che continui a bloccarsi mi stupisce, e per verificarlo devo metterlo sul compilatore, ma ho bisogno di tutto il codice in questione.
  • Re: Segmentation fault

    Mmh intendi il main?

    Nel caso fosse quello te lo copio:
    #include <stdlib.h>
    #include <string.h>
    #include "../libtest/libtest.h"
    #include "test.h"
    #include "scl.h"
    #include "esercizio.h"
    
    int main(int argc, char** argv){
        TipoSCL scls[10];
        scls[0] = NULL;
        scls[1] = nuovo(1,NULL);
        scls[2] = nuovo(5,NULL);
        scls[3] = nuovo(1,nuovo(3,NULL));
        scls[4] = nuovo(1,nuovo(5,NULL));
        scls[5] = nuovo(5,nuovo(3,nuovo(1,NULL)));
        scls[6] = nuovo(1,nuovo(3,nuovo(5,NULL)));
        scls[7] = nuovo(3,nuovo(3,nuovo(5,nuovo(5,NULL))));
        scls[8] = nuovo(5,nuovo(5,nuovo(3,nuovo(3,NULL))));
        scls[9] = nuovo(5,nuovo(5,nuovo(5,nuovo(5,nuovo(5,NULL)))));
        
        int m = 3;
    
        int scls2[10][10] = {
            {0,0,0,0,0,0,0,0,0,0},
            {0,0,0,0,0,0,0,0,0,0},
            {5,0,0,0,0,0,0,0,0,1},
            {0,0,0,0,0,0,0,0,0,0},
            {5,0,0,0,0,0,0,0,0,1},
            {5,0,0,0,0,0,0,0,0,1},
            {5,0,0,0,0,0,0,0,0,1},
            {5,5,0,0,0,0,0,0,0,2},
            {5,5,0,0,0,0,0,0,0,2},
            {5,5,5,5,5,0,0,0,0,5}
        };
        
    	test_reset();
    	TipoSCL scl;
    	
    	for (int i = 0; i < 10; i++) {
    		print_test_start(i+1);
    		printf("Funzione: maggioriDi\n");
    		printf("Input: %s\n", toString(scls[i]));
            int n;
            int* ris = maggioriDi(scls[i],m,&n);
    		test_compare_array_int(scls2[i],scls2[i][9],ris,n);
    		print_test_end();
    		print_n_success("#Test superati: ");
    	}
    	print_test_result("Percentuale test corretti:");
    }
  • Re: Segmentation fault

    int conta (TipoSCL scl, int m) {
        if (scl==NULL)
            return 0;
    
        if (scl->info > m) {
            return 1+conta (scl->next,m);
        }
        return conta(scl->next, m);
    }
    
    void controlla (TipoSCL scl, int m, int *ris, int *a) {
        if (scl == NULL) {
            return;
        }
        if (scl->info > m) {
            ris[(*a)++]=scl->info;
            controlla(scl->next, m, ris, a);
        } else {
            controlla(scl->next, m, ris, a);
        }
    }
    Adesso funziona! Il problema sta ne comprendere che le funzioni ricorsive vanno chiuse tutte, non puoi bucare la ricorsione e chiudere tutte con l'ultimo return. Capisco che è un concetto non immediato, ma superato questo scoglio penso che la ricorsione sia abbastanza addomesticabile.
  • Re: Segmentation fault

    Grazie mille! In effetti è un po' ostico da capire il concetto
Devi accedere o registrarti per scrivere nel forum
7 risposte