PDA

Visualizza la versione completa : C Errore stack trace e segm fault


VYCanisMajoris
15-02-2012, 00:34
Salve ragazzi! Sono alle prese con un programmino che mi da difficoltà, leggete il seguito!
Il programma è cosi strutturato:
una strut Data con i membri, gg, mm, aa
Un array dinamico di elementi Data
4 funzioni:
-2 funzioni si occupano dell'input:
-----una si occupa di prendere in input un solo elemento
-----l'altra chiamando in modo ciclico la precedente memorizza tutti gli elementi fino a che la variab sentinella ctrl vale 1
-2 funzioni si occupano dell''output
-----hanno la stessa logica di quelle di input solo che non c'è, ovviamente la sentinella

Ok ragazzi ecco il codice, spero che ora mi potrete aiutare con piu semplicità :-) vi ringrazio


#include <stdio.h>
#include <stdlib.h>
struct Data {
int gg;
int mm;
int aa;
};typedef struct Data Data;

/* Prototipi */
Data input_singolo( void );
void stampa_singolo( Data x );
int input_tutti( Data* V, int* nE );
void stampa_tutti( Data* V, int n );

int main(void) {

Data* Vett = NULL;
int numEl = 0;

int istr = input_tutti( Vett, &numEl );
stampa_tutti( Vett, numEl );

return 0;
}

/* Prende in input tutti gli elementi di V.
* riceve V ed un puntatore alla var numEl.
* col puntatore salva il numero di elementi dell'array,
* e ritorna il valore immesso a ctrl */
int input_tutti( Data* V, int* nE ) {
int i = *nE;
int ctrl = 0;
while( ctrl != 1 ) {
V = realloc( V, (i+1)*sizeof(Data) );
V[i++] = input_singolo();
printf( "Immettere 1 per fermare l'inserimento, immettere 0 per continuare: " );
scanf( "%d", &ctrl );
}
*nE = i;
return ctrl;
}

/* stampa tutti gli elementi di V */
void stampa_tutti( Data* V, int n ) {
for( int i = 0; i < n; i++ ) {
stampa_singolo( V[i] );
}
}

/* prende in input un elemento di tipo Data */
Data input_singolo( void ) {
Data x;
printf("Inserire data (g/m/a): ");
scanf( "%d/%d/%d", &x.gg, &x.mm, &x.aa );
return x;
}

/* stampa singolo elemento */
void stampa_singolo( Data x ) {
printf("%d/%d/%d\n", x.gg, x.mm, x.aa);
}

Errore:

3@tre ~
$ gcc -Wall -std=c99 a.c -o a.exe
a.c: In function ‘main’:
a.c:20:6: warning: unused variable ‘istr’

3@tre ~
$ ./a.exe
Inserire data (g/m/a): 29/7/1990
Immettere 1 per fermare l'inserimento, immettere 0 per continuare: 0
Inserire data (g/m/a): 7/6/1991
Immettere 1 per fermare l'inserimento, immettere 0 per continuare: 1
Exception: STATUS_ACCESS_VIOLATION at eip=00401283
eax=00000000 ebx=00000000 ecx=20000037 edx=00000000 esi=61268A54 edi=6119DD5F
ebp=0022CC98 esp=0022CC70 program=C:\cygwin\home\3\a.exe, pid 1668, thread main
cs=001B ds=0023 es=0023 fs=003B gs=0000 ss=0023
Stack trace:
Frame Function Args
0022CC98 00401283 (00000000, 00000002, 0022CCE8, 49435341)
0022CCC8 004011BA (00000001, 0022CCF0, 20010100, 612671DE)
0022CD58 61006EE8 (00000000, 0022CDA8, 610064E0, 00000000)
End of stack trace
Segmentation fault (core dumped)

3@tre ~
$

ramy89
15-02-2012, 02:32
Hai fatto bene a postare l' input del terminale, così è chiaro.
Innanzitutto con la realloc,siccome ritorna un puntatore a void, anche se il tipo Data* è compatibile col tipo void*,è sempre meglio effettuare un cast a Data*.
Poi tu passi come parametro Vett, che è un puntatore.
Ma il puntatore originario rimane intatto: infatti se provi a stampare dopo la chiamata a input_tutti il valore di Vett, è sempre NULL.
La input_tutti, come una qualsiasi altra funzione, fa solo una copia di quel puntatore.
Per cui alla fine della funzione avrai perso il riferimento a quella memoria.
Altra cosa: chiami la realloc senza che ci sia stata allocata memoria.Quando i=1 chiama la malloc.
Inoltre è meglio controllare che la malloc e la realloc non ritornino NULL.
Puoi usare le asserzioni di assert.h , o exit(int).
Ecco il codice corretto:


int input_tutti( Data** V, int* nE ) {
int i = *nE;
int ctrl = 0;
while( ctrl != 1 ) {
i++;
if(i>1)
*V = (Data*)realloc( *V, i*sizeof(Data) );
else
*V=(Data*)malloc(sizeof(Data));
assert(*V!=NULL);
(*V)[i-1] = input_singolo();
printf( "Immettere 1 per fermare l'inserimento, immettere 0 per continuare: " );
scanf( "%d", &ctrl );
}
*nE = i;
return ctrl;
}

VYCanisMajoris
16-02-2012, 16:24
Chiarissimo e gentilissimo, ti ringrazio tanto :ciauz:

Loading