Visualizzazione dei risultati da 1 a 4 su 4
  1. #1

    [C] Errore Seg, solo se il file ha piu di 57 righe

    Vi scrivo perchè mi succede una cosa molto strana. Il programma che vi sto sottoponendo legge rigaper riga da un file, ne estrapola solo gli zeri e gli uni e poi li salva in una matrice dinamica che viene alla fine stampata.
    Il problema sussiste solo se il file supera le 57 righe. Se ci sono 57 righe precise, tutto bene.

    Programma:
    codice:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    char* estrapolaDati(char* d, char strRD[]);
    int** riempieMatriceDinamica(int** m, int* rPtr, char d[]);
    
    int main(void) {
    
    	// --->
    	int nRighe = 0, nColonne = 0;
    	int** matrice; 					/* matrice con 0 righe e 0 colonne */
    	matrice = malloc((nRighe+1)*sizeof(int*)); 	/* creata prima riga di 0 colonne */
    	matrice[0] = malloc((nColonne+1)*sizeof(int)); 	/* creata, nella prima riga, una colonna, ora si ha una matrice con una sola casella*/
    	// <---
    
    	char strRawDati[100];
    	FILE *fPtr;
    	if( (fPtr = fopen("q_item.csv", "r")) == NULL ) {
    		printf("Problema con l'apertura del file\n");
    	}
    	
    	char* dati;
    	while( !feof(fPtr) ) {
    		fscanf(fPtr, "%s", strRawDati);		/* legge il record corrente dal file memorizzandolo in strRaw*/
    		if(strRawDati[0] == 'F') {		/* se il record ha come primo carattere una 'F', allora contiene dati */
    			dati = estrapolaDati(dati, strRawDati);
    			nColonne = strlen(dati);
    			matrice = riempieMatriceDinamica(matrice, &nRighe, dati);
    		}
    	}
            fclose(fPtr);
    
    	/* stampa matrice dinamica */
    	for(int i=0 ; i<nRighe ; i++) {
    		for(int j=0 ; j<nColonne ; j++) {
    			printf(" %d", matrice[i][j]);
    		}
    		printf("\n");
    	}
    	return 0;
    }
    
    /*
     * @param1 int** m   : matrice dinamica da riempire
     * @param2 int r     : riga attuale da creare e riempire
     * @param3 char d[]  : dati con cui riempire la riga della matrice dinamica
     */
    int** riempieMatriceDinamica(int** m, int* rPtr, char d[]) {
    	int r = *rPtr;
    	r++;						/* incrementa r per allocare la quantità corretta di "righe" nella matrice */
    
    	m = realloc(m, r*sizeof(int*));
    	m[r-1] = realloc(m[r-1], (strlen(d))*sizeof(int));
    
    	for(int i=0 ; i<strlen(d) ; i++) {
    		if(d[i] == '0')
    			m[r-1][i] = 0;
    		else
    			m[r-1][i] = 1;
    	}
    	*rPtr = r;	
    
    	return m;
    }
    
    /*
     * @param1 char* d     : array di char dinamico in cui verranno salvati SOLO gli zeri e gli uno
     * @param2 char strRD[]: array di char "sporco" da cui verranno estrapolati SOLO gli zeri ed uno
     */
    char* estrapolaDati(char* d, char strRD[]) {
    	int i = strlen(strRD);
    	i = i - 1;					/* l'indice di scorrimento deve partire da destra */
    	/* scorre la stringa da dx a sx finchè incontra 
    	 * una ',' && una 'lettera' a sinistra della ','
    	 * allora in i+1 si troverà il primo dato da salvare */
    	while( !( isalpha(strRD[i-1]) && strRD[i] == ',' ) ) {
    		i--;
    	}
    	i = i + 1; //indice di partenza per la copia dei dati dalla stringa strRD a d
    
    	/* copia i dati da strRD a d */
    	int dIndex = 0;
    	d = malloc(sizeof(int));
    	for( ; strRD[i] != '\0' ; i++) {
    		if(strRD[i] == '0') {
    			d = realloc(d, (dIndex+1)*sizeof(int));
    			d[dIndex] = '0';
    			dIndex++;
    		}
    		else if(strRD[i] == '1') {
    			d = realloc(d, (dIndex+1)*sizeof(int));
    			d[dIndex] = '1';
    			dIndex++;
    		}
    	}
    	d = realloc(d, (dIndex+1)*sizeof(int));
    	d[dIndex] = '\0';
    
    	return d;
    }
    Poi c'è un altro piccolo problemino ma questo è di secondaria importanza, non capisco perche mi stampa due volte l'ultima riga del file.(Sempre usando un file da 57 righe e non da 58 che non funziona nulla)

  2. #2
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772
    Si tratta di un errore semantico nella funzione riempieMatriceDinamica() ed in particolare della seconda chiamata a realloc().

    (gdb) backtrace
    #0 0xb7ee0f03 in realloc () from /lib/tls/i686/cmov/libc.so.6
    #1 0x080488a7 in riempieMatriceDinamica (m=0x804cdb0, rPtr=0xbffff3f4, d=0x804cd40 "011000101011") at html.c:58
    #2 0x08048798 in main () at html.c:32
    Command execution time: 0.004000
    Space used: 1515520 (+0 for this command)


    Il problema non è tanto la riga 58 in se, quanto che reallocando la memoria, finisci con l'accedere ad un'area non tua. Se sostituisci la riga in questione con m[r-1] = malloc((strlen(d))*sizeof(int)); funziona tutto correttamente (dovresti deallocare la precedente in realta).
    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

  3. #3
    ti ringrazio, hai ragione, così funziona!
    Solo che non riesco a capire il perche riallocando vado a finire in zone non mie mentre se alloco rimango in zone mie.
    Probabilmente c'è qualche lacuna nelle mie conoscienze. Io so che:
    realloc: si usa quando ad esempio l'array in esame ha gia una dimensione e la devi appunto aumentare. Usando realloc in un array che non ha dimensione ad esempio un puntatore a int da errore
    malloc: si usa quando l'array in esame non ha dimensione, quindi siamo nel caso in cui ad esempio abbiamo un puntatore a int e vogliamo allocare n spazi.

    Forse è in questa mia conoscenza errata che si sviluppa l'errore che ho fatto?

  4. #4
    Utente di HTML.it L'avatar di infinitejustice
    Registrato dal
    Nov 2001
    residenza
    Barcelona
    Messaggi
    772
    Guarda, che il problema sia la call a realloc() è sicuro al 100%. Sul perchè il mio ragionamento nasce semplicemente dalla definizione di realloc:


    man realloc

    void *realloc(void *ptr, size_t size);

    realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated memory will be uninitialized. If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc(). If the area pointed to was moved, a free(ptr) is done.


    Volendo potresti fare un trace con GDB e guardare cos'è contenuto in quella cinquantottesima area di memoria prima che sia passata a realloc.

    Al della ragione, ricorda che un realloc è una operazione costosa (nel momento in cui riallochi, stai occupando N + N-1 spazio visto che la macchina deve copiar tutti gli elementi). Potresti semplicemente far un malloc + free e via.
    Live fast. Troll hard.
    Pythonist | Djangonaut | Puppeteer | DevOps | OpenStacker | Lost in malloc
    Team Lead @Gameloft Barcelona

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.