PDA

View Full Version : [C] Un aiuto please, sono disperato... Allocazione dinamica, più o meno...


Zero-Giulio
04-02-2009, 17:57
Allora, sono disperato...

Vediamo se mi riesce di esprimere chiaramente il mio problema.

Allora, ho questa struttura:


struct nodes
{
double x;
double y;
double z;
};

typedef struct nodes nodes;
typedef struct nodes *nodesptr;


Successivamente, leggo un intero num_elements e decido di creare una matrice num_elementsx4 di quelle struct. Faccio:


gradients=(nodesptr *) malloc ((num_elements+1)*sizeof (nodesptr));
if (*gradients == NULL)
{
printf ("\nError: no memory available for gradients structure.\n");
return 0;
}
for (i=1; i<=num_elements; i++)
{
gradients [i]=(nodesptr) malloc ((4)*sizeof (nodes));
if (gradients == NULL)
{
printf ("\nError: no memory available for gradients structure.\n");
return 0;
}
}


Ok. Compilo. Eseguo. Non vedo nessun messsaggio di errore, quindi penso che non ci sono stati problemi nel creare la matrice.

Quini decido di inizializzare:


for (i=1; i<=num_elements; i++)
for (j=0; j<4; j++)
{
gradients [i][j].x=0.0;
gradients [i][j].y=0.0;
gradients [i][j].z=0.0;
}


e qui il programma crasha:
Process returned -1073741819 (0xC000000%) execution time: 5.562 s. Press any key to continue.

(Lavoro su Xp con Code::Blocks).

Il bello è che se faccio:



for (i=1; i<=60; i++)
for (j=0; j<4; j++)
{
gradients [i][j].x=0.0;
gradients [i][j].y=0.0;
gradients [i][j].z=0.0;
}


il programma funziona correttamente, mentre se faccio:



for (i=1; i<=65; i++)
for (j=0; j<4; j++)
{
gradients [i][j].x=0.0;
gradients [i][j].y=0.0;
gradients [i][j].z=0.0;
}


no, da lo stesso errore che mi da con num_elements (che è 105, nelle prove che sto facendo).

Non so dove sbattere la testa.

Cosa c'è che non va?

Non alloca tutta la matrice?

Perchè le prime 60 righe si, e le altre no?

Perchè non me lo dice quando faccio i controlli?

Secondo voi è il caso di cambiare ide? Non so, è un bug di Code::Blocks?

Madò, son due giorni che debuggo riga per riga il codice, finalmente ho trovato dove si ingrippa il programma, ma non so cosa fare... :-(

cionci
04-02-2009, 18:29
Questo è errato:

gradients=(nodesptr *) malloc ((num_elements+1)*sizeof (nodesptr));
if (*gradients == NULL)
{
printf ("\nError: no memory available for gradients structure.\n");
return 0;
}
for (i=1; i<=num_elements; i++)
{
gradients [i]=(nodesptr) malloc ((4)*sizeof (nodes));
if (gradients == NULL)
{
printf ("\nError: no memory available for gradients structure.\n");
return 0;
}
}
Devi togliere l'asterisco nel primo caso, devi controllare che il puntatore non sia NULL, non il suo contenuto.
Nel secondo devi controllare che grandients[i] sia diverso da NULL.

Zero-Giulio
05-02-2009, 16:38
Uff, si, certo hai ragionissima.

Ok, modificato, e...

Non mi da più errore. Mi fa strano, se fosse mancata la memoria sarebbe dovuto uscire il msg di errore, invece adesso funzia tutto. Allora perchè prima il programma si comportava in modo strano (allocando solo 60 posizioni?).

Boh, vabbè, almeno quella funzione ora gira.

Adesso, purtroppo, ho problemi con la funzione dopo.

Stralcio di codice (anche qui, solo allocazione di memoria):


printf ("dentro1");
system ("PAUSE");
M1=(double **) malloc ((num_edges+1)*sizeof (double *));
if (M1 == NULL)
{
printf ("\nError: no memory available for M1 matrix.\n");
return 0;
}
printf ("dentro2");
system ("PAUSE");
for (i=1; i<=num_edges; i++)
{
M1 [i]=(double *) malloc ((num_edges+1)*sizeof (double));
if (M1 [i] == NULL)
{
printf ("\nError: no memory available for M1 matrix (colomn %ld).\n", i);
return 0;
}
}


Qui il programma si interrompe.

Stampa a video "dentro1", quindi prima della prima malloc, ma non stampa a video "dentro2".

Si interrompe.

Anche qui, suggerimenti?

(sono depresso...)

cionci
05-02-2009, 16:49
Che intendi per "si interrompe"...va in ciclo infinito ? Esce ?

Zero-Giulio
05-02-2009, 17:16
No, nessun ciclo infinito. Esce...

Semplicemente, si interrompe.

Process returned -1073741819 (0xC0000005) execution time: 5.515 s
Press any key to continue.

Ma non dovrebbe interrompersi, il programma deve continuare ancora per un pò.

Infatti vedo a video "dentro1", poi si interrompe prima del "dentro2". Non capisco quale problema abbia.

Che sia il compilatore?

cionci
05-02-2009, 17:21
Quel codice è corretto. L'errore è sicuramente altrove.

PS: stai attento ad utilizzare i vettori non zero-based.

Zero-Giulio
05-02-2009, 17:36
In che senso?

Cosa non dovrei fare?

cionci
05-02-2009, 17:39
Un vettore C di dimensione N può essere indicizzato tramite gli indici che vanno da 0 a N-1.

Ora questo:

for (i=1; i<=num_edges; i++)

è utilizzo sbagliato dei vettori in C. Primo perché lasci l'elemento zero inutilizzato (spreco di memoria), secondo perché può portare ad errori. In questo caso avevi previsto un elemento in più (hai allocato num_edges+1 nella prima malloc), ma in generale è una pratica altamente scoraggiata.

Zero-Giulio
05-02-2009, 20:38
No, diventa un macello utilizzare gli indici che partono da zero.

Normalmente io parto da zero, come andrebbe sempre fatto, ma in questo caso non potevo, per alcuni motivi.

Cmq... Anzitutto, grazie mille per la disponibilità, la pazienza e la celerità delle tue risposte.

Ora, sono riuscito a far arrivare il programma fino alla fine, cambiando qualche riga di codice.

Sembrerebbe che io abbia risolto, ma non ho capito COME ho risolto. In pratica, l'unico cambiamento che ho fatto è questo:

facendo riferimento al mio primo post (quello con gradient): ho tolto la malloc! Praticamente nel main ho messo:


struct nodes gradients [(num_elements+1)][4];


(num_elements in quel momento è noto, naturalmente)
e poi ho cambiato l'intestazione della funzione, da


int find_gradients ()


a


int find_gradients (struct nodes gradients [][4])


quindi, dentro la find_gradients, non serve più la malloc e lavoro normalmente.

Fatto questo, tutto il programma sembra funzionare senza problemi (nel senso che riesce tranquillamente ad arrivare alla fine).

Ne deduco che, quindi, tutto il resto del codice era corretto. Da cui i miei dubbi sulla natura dei problemi che avevo.

Di cosa si trattava?

Due dubbi in particolare:

1 - di funzioni come la gradients ne ho 9 nel programma. Tutte del tipo: alloco, riempio, eventualmente ridimensiono, tutte che lavorano su variabili extern dichiarate nel main ecc...

Tutte identiche cmq, cambiano i nomi delle variabili e il loro tipo, ma le routine sono praticamente uguali. Anche il modo di usare gli indici, è uguale per tutte.

Nessuna dava problemi, se non la find_gradients (e il lavoro di sostituire la malloc con la dichiarazione nel main l'ho fatto solo per lei).

L'unica peculiarità che mi viene in mente riguardo la find_gradients, è che lei non lavora su un tipo standard (double, int ecc...), ma su una struct da me definita

2 - in realtà anche com'era scritta prima, la find_gradients funzionava. Quello che non funzionava, era tutto quel che seguiva. Praticamente:

con la malloc in find_gradients: find_gradients funzionava, ma non funzionava niente dopo (i problemi di cui parlavo, il programma terminava bruscamente alla malloc della funzione dopo find_gradients, cioè alla funzione di cui parlavo nel mio secondo post)

senza la malloc nel find_gradients: la find_gradients continua a funzionare e funzioano bene anche le altre funzioni che vengono dopo di lei.

...


Sembra tutto molto strano, ma è così. E' tutto il pomeriggio che ci sbatto la testa. E' scritto system ("PAUSE") e printf ovunque, per vedere fin dove arrivava il programma e a quale riga si bloccava.

Il problema sono le malloc. Se metto la malloc in find_gradients, poi tutte le malloc successive non funzionano. Non so perchè.

Qualche idea?

Chiedo perchè non mi piace la soluzione che ho adottato: manca di simmetria con il resto del codice, e mi costringe a fare una dichiarazione nel bel mezzo del programma, oltre che a dover passare la matrice gradients come argomento di tutte le funzioni successive (prima la usavo come extern).

Zero-Giulio
06-02-2009, 09:40
Ho risolto!!!!!!!!!!

Ecco cosa dovevo fare:

da

gradients=(nodesptr *) malloc ((num_elements+1)*sizeof (nodesptr));
if (*gradients == NULL)
{
printf ("\nError: no memory available for gradients structure.\n");
return 0;
}
for (i=1; i<=num_elements; i++)
{
gradients [i]=(nodesptr) malloc ((4)*sizeof (nodes));
if (gradients == NULL)
{
printf ("\nError: no memory available for gradients structure.\n");
return 0;
}
}


a


gradients=(struct nodes **) malloc ((num_elements+1)*sizeof (struct nodes *));
if (gradients == NULL)
{
printf ("\nError: no memory available for gradients structure.\n");
return 0;
}
for (i=0; i<=num_elements; i++)
{
gradients [i]=(struct nodes *) malloc ((4)*sizeof (struct nodes));
if (gradients [i] == NULL)
{
printf ("\nError: no memory available for gradients structure (colomn %ld).\n", i);
return 0;
}
}


Praticamente, anche se nodes e nodesptr erano stati definiti con typedef, io dovevo scrivere cmq struct. Serve il nome esteso.

Il dubbio mi era venuto dal fatto che non potevo passare


nodes gradients [][4]


come argomento di funzione (mi dava errore di compilazione), ma dovevo scrivere tutto per esteso:


struct nodes gradients [][4]


Quindi ho pensato che fosse lo stesso nella malloc. In effetti nella malloc non dava errore di compilazione, ma dava errori di esecuzione come già detto.

Quindi ok, problema capito.

Giusto per curiosità, è normale che vada messa la parola struct nella malloc, oppure è un bug del compilatore?

cionci
06-02-2009, 11:31
A parte i controlli sugli if che ti avevo già corretto...per il resto sono assolutamente equivalenti. struct non serve su un typedef.

Qui però in effetti serviva:

gradients [i]=(nodesptr) malloc ((4)*sizeof (nodes));

Però strano che non abbia dato errore in compilazione :boh:

Zero-Giulio
06-02-2009, 14:38
Si, le condizioni sugli if erano sbagliate, ma non erano quello il problema.


Anche quando scritte giuste, non cambiava niente: il msg di errore cmq non usciva, quindi non era la mancanza di memoria il problema.

Il problema si è risolto con la struct nella malloc.

Cmq sono arrabbiato con Code::Blocks. Perchè non me lo ha detto in fase di compilazione.

Sono rimasto un giorno intero a sbatterci la testa. Dispiace perdere tempo per queste cose...

Giusto che ci sono, consigli altri ambienti per programmare in C?

(prima usavo Dev-C++, ma poi sentivo in giro che era buggatissimo, anche se in effetti io non ho mai avuto provlemi).

Grazie di tutto, naturalmente!

Torav
06-02-2009, 15:39
gli errori che ti vengono dati in fase di compilazione non dipendono dall'IDE con cui scrivi il codice ma dal compilatore che utilizzi. Potresti cmq provare a dare qualche flag in più in fase di compilazione in modo da avere tutti i warning (-Wall per esempio)

Zero-Giulio
06-02-2009, 17:12
Potresti guidarmi, un attimino?

Considerando che non sono molto pratico nello scrivere codice, forse mi converebbe attivare molti flag (tutti? Quali controindicazioni si hanno?).

Cosa consigliate? (io ho lasciato di default per adesso)

Torav
06-02-2009, 17:53
sicuramente ti consiglio -Wall (in pratica ti dà tutti i warning possibili :p ). Per essere sicuro di non perdertene nessuno puoi mettere anche -pedantic (mai fu dato nome più esplicativo ad un flag :D ). Se vuoi fare le cose per bene rispettando gli standard (il che *potrebbe* voler dire che scrivi codice facilmente portabile su altri sistemi/con altri compilatori) puoi mettere un -std=C99
Se non vuoi mettere tutti i warning puoi vedere le alternative a -Wall, per esempio googlando ho trovato questo (http://developer.apple.com/DOCUMENTATION/DeveloperTools/gcc-3.3/gcc/Warning-Options.html#Warning-Options) che non sembra male! Puoi dare un'occhiata e scegliere cosa ti conviene mettere e cosa no!

cionci
06-02-2009, 19:43
Prima di tutto...che estensione ha il tuo file sorgente ? .c o .cpp ?

Zero-Giulio
06-02-2009, 21:24
Ho un .h e sette .c