View Full Version : [C] la "calloc" patisce il caldo???
Gandalf_BD
29-06-2006, 19:29
Ciao a tutti...
ho un problemino stranissimo nell'allocazione di una matrice di int...
ecco il codice:
...
dipendenze = (int **) calloc(n_ops, sizeof(int *));
for(i = 0; i < n_ops; i++)
dipendenze[i] = (int *) calloc(n_ops, sizeof(int));
...
ora... ho controllato con gdb che il valore di n_ops fosse giusto, e così è...
n_ops vale 7...
secondo voi, com'è possibile che la calloc allochi la memoria come se n_ops valesse solo 4?????
se io, dopo aver allocato la matrice, faccio un bel "print sizeof(dipendenze)" il risultato è 4 e non 7 come dovrebbe essere... :confused: :what: :what:
scommetto che è un errore stupido (in genere è sempre così :D), ma non riesco proprio a vederlo... :muro: :bsod:
secondo voi dove sbaglio?
grazie :)
Ziosilvio
29-06-2006, 19:40
se io, dopo aver allocato la matrice, faccio un bel "print sizeof(dipendenze)" il risultato è 4 e non 7 come dovrebbe essere
Il risultato è 4, ossia presumibilmente la lunghezza in byte di una parola di memoria: come deve essere dal momento che dipendenze è un puntatore e non un array.
Va detto comunque che la relazione tra array e puntatori viene molto mitizzata e poco capìta.
Dài un'occhiata a c-faq.com (http://c-faq.com/), il sito delle FAQ del newsgroup comp.lang.c, alla sezione 6.
Gandalf_BD
29-06-2006, 20:38
vabè, ma scusa.... :mbe:
non dovrebbe allocarmi comunque una matrice 7x7??
invece, gliela faccio stampare ed è una 4x4... :muro:
Gandalf_BD
29-06-2006, 22:02
aggiornamento:
il ciclo lo fa 6 volte (anzichè 7) e però ne alloca solo 4... :mbe: :mbe:
sto impazzendo... :muro: :muro:
sul mio pc ho l'unica calloc in grado di decidere da sola quanto deve allocare :D
ps: per sicurezza, ho provato anche con la malloc, ma fa la stessa cosa... il fatto è che finchè non riesco ad allocare la memoria, sono bloccato, perchè non posso debuggare...
Ziosilvio
29-06-2006, 22:04
non dovrebbe allocarmi comunque una matrice 7x7?
La matrice allocata è 7x7: solo che non è sizeof(dimensione) che te lo può dire, perché dimensione è una variabile di tipo puntatore, quindi sizeof(dimensione) è lo stesso che sizeof(void*), e non ha niente a che vedere con la memoria effettivamente allocata.
...
dipendenze = (int **) calloc(n_ops, sizeof(int *));
for(i = 0; i < n_ops; i++)
dipendenze[i] = (int *) calloc(n_ops, sizeof(int));
...
secondo voi dove sbaglio?Il pezzo di codice che hai postato è corretto. Se n_ops in quel momento vale 7, deve per forza allocare una matrice di int di 7x7.
Presumo che il problema sia da qualche altra parte.
Gandalf_BD
29-06-2006, 22:07
nono... non hai capito... ho forse mi sono spiegato male io :D
lasciando perdere sizeof, quando provo a fargliela stampare, mi stampa solo una 4x4 e infatti, se provo ad accedere alle altre caselle, mi da un Segmentation fault...
lasciando perdere sizeof, quando provo a fargliela stampare, mi stampa solo una 4x4 e infatti, se provo ad accedere alle altre caselle, mi da un Segmentation fault...Puoi postare il codice che stampa la matrice??
Gandalf_BD
29-06-2006, 22:18
Puoi postare il codice che stampa la matrice??
no... ehm... quello era sbagliato :D:D:D
perchè come limite mettevo sizeof() che quindi ritornava 4...
la situazione ora è questa: la memoria è allocata giusta, ma quando provo a cambiare un valore della matrice (da 0 a 1) mi da nuovamente SegFault...
vi posto il codice intero, vah...
#include <stdio.h>
#include <string.h>
#define LENGTH 21
#define MAX_LENGTH 255
int **dipendenze, flag = 0, dipend = 0;
typedef struct {
char nome[LENGTH];
int tipo;
int durata;
} Operazione;
Operazione *operazioni;
void load_file(void);
void print_dip(void);
void main (void)
{
load_file();
print_dip();
}
void load_file(void) {
FILE *fp;
int n_ops, i, j, tempo_tmp, op_tmp, op1, op2;
char temp[MAX_LENGTH], nome_tmp[LENGTH], tipo_tmp[4], nome1[LENGTH], nome2[LENGTH];
fp = fopen("dati.txt", "r");
if(fp == NULL) {
printf("Unable to open dati.txt\n");
return;
}
fgets(temp, MAX_LENGTH, fp);
sscanf(temp, "%d", &n_ops);
operazioni = (Operazione *) calloc(n_ops, sizeof(Operazione));
dipendenze = (int **) calloc(n_ops, sizeof(int *));
for(i = 0; i < n_ops; i++)
dipendenze[i] = (int *) calloc(n_ops, sizeof(int));
for(i = 0; i < n_ops; i++)
for(j = 0; j < n_ops; j++)
dipendenze[i][j] = 0;
print_dip();
for(i = 0; i < n_ops; i++) {
fgets(temp, MAX_LENGTH, fp);
sscanf(temp, "%s %s %d", nome_tmp, tipo_tmp, &tempo_tmp);
op_tmp = nome_tmp[2] - '0';
strncpy(operazioni[op_tmp].nome, nome_tmp, strlen(nome_tmp));
if(!(strncmp(tipo_tmp, "AND", strlen(tipo_tmp)))) {
flag = 1;
operazioni[op_tmp].tipo = 1;
} else {
operazioni[op_tmp].tipo = 0;
}
operazioni[op_tmp].durata = tempo_tmp;
}
while(fgets(temp, MAX_LENGTH, fp)) {
sscanf(temp, "%s %s", nome1, nome2);
op1 = nome1[2] - '0';
op2 = nome2[2] - '0';
dipendenze[op1][op2] = 1;
}
fclose(fp);
}
void print_dip(void) {
int i = 0, j = 0;
for(i = 0; i < 7; i++) {
for(j = 0; j < 7; j++)
printf("%d", dipendenze[i][j]);
printf("\n");
}
}
al momento del SefFault op1 e op2 valgono rispettivamente 4 e 5, per cui non dovrebbero esserci problemi... la riga incriminata è "dipendenze[op1][op2] = 1;"
grazie mille :)
Ziosilvio
29-06-2006, 23:00
sscanf(temp, "%s %s %d", nome_tmp, tipo_tmp, &tempo_tmp);
Com'è formattato il tuo file di dati?
Se ricordo bene, una chiamata del tipo scanf("%s%s",s1,s2) continua a inserire caratteri in s1 finché non incontra un newline.
Se le righe hanno la forma "parola, spazio, parola, spazio, numero, a capo" allora o scansioni una riga alla volta, la spezzi con strtok, e poi la elabori; oppure usi tab al posto di spazio come separatore e usi "%s\t%s\t%n" come stringa di formato.
EDIT: ricordavo male, si ferma agli spazi :cry:
op_tmp = nome_tmp[2] - '0';
Questo restituisce il valore del numero rappresentato dal carattere nome_tmp[2], a condizione che i caratteri delle dieci cifre siano consecutivi: il che avviene in ASCII ma non in EBCDIC.
while(fgets(temp, MAX_LENGTH, fp)) {
sscanf(temp, "%s %s", nome1, nome2);
op1 = nome1[2] - '0';
op2 = nome2[2] - '0';
dipendenze[op1][op2] = 1;
}
fclose(fp);
}
Stessa osservazione di poco fa: a questo punto, i valori di op1 e op2 potrebbero non essere interi fra 0 e 9.
sottovento
30-06-2006, 04:52
Ciao,
alcuni suggerimenti:
1 - La matrice e' globale. Ti devi portare dietro anche le sue dimensioni, visto che la sizeof() non ti puo' aiutare (hai allocato dinamicamente).
Pertanto metti n_ops allo stesso livello di visibilita', cosi' quando accedi alla matrice puoi anche accedere alle sue dimensioni;
2 - cambia il codice di allocazione con:
dipendenze = (int **) calloc(n_ops, sizeof(int *));
if (!dipendenze)
{
printf ("Errore allocazione memoria\n");
exit (0);
}
for(i = 0; i < n_ops; i++)
{
dipendenze[i] = (int *) calloc(n_ops, sizeof(int));
if (!dipendenze[i])
{
printf ("Errore allocazione della riga %d\n", i);
exit(0);
}
}
In questo modo ti puoi accorgere se una delle linee non e' stata allocata correttamente.
3 - cambia la void print_dip() di conseguenza:
void print_dip(void) {
int i = 0, j = 0;
for(i = 0; i < n_ops; i++) {
for(j = 0; j < n_ops; j++)
printf("%d", dipendenze[i][j]);
printf("\n");
}
Una volta fatte queste operazioni, hai qualche chance in piu' di capire cosa succede nel tuo programma.
4 - Prima di accedere alla matrice, controlla gli indici, che siano inferiori a n_ops. La sicurezza non e' mai troppa.
Analogamente, controlla che n_ops sia > 0.
5 - Il fatto che tu abbia un crash di quel genere suggerisce davvero che gli indici siano fuori range. Puoi fare un ulteriore controllo?
Spero che questi suggerimenti ti possano aiutare
High Flying
Sottovento
Gandalf_BD
30-06-2006, 08:10
grazie a tutti :)
cmq io ho già fatto numerosi controlli...
fino al punto in cui cerco di cambiare l'elemento della matrice va tutto bene (controllato con gdb), il problem asi presenta lì...
il fatto è che i due indici sono nel range corretto, uno vale 4 e l'altro vale 5, mentre n_ops vale 7...
:cry: :cry: :cry:
EDIT: in più, pensavo che poche righe sopra, l'azzeramento della matrice me lo fa correttamente e senza problemi... quindi non è un problema di allocazione... :muro:
EDIT2: se con gdb provo ad accedere a quel valore (print dipendenze[4][5]) mi dice: "Cannot access memory at address 0x15"... ma se provo ad accedere a quel valore poche righe sopra (subito dopo l'azzeramento) non ho nessun problema e mi stampa il valore giusto..
trallallero
30-06-2006, 08:35
grazie a tutti :)
cmq io ho già fatto numerosi controlli...
fino al punto in cui cerco di cambiare l'elemento della matrice va tutto bene (controllato con gdb), il problem asi presenta lì...
il fatto è che i due indici sono nel range corretto, uno vale 4 e l'altro vale 5, mentre n_ops vale 7...
:cry: :cry: :cry:
EDIT: in più, pensavo che poche righe sopra, l'azzeramento della matrice me lo fa correttamente e senza problemi... quindi non è un problema di allocazione... :muro:
ma il problema c'e' ancora ?
se si, puoi postare il file che carichi ?
Gandalf_BD
30-06-2006, 08:40
si, il problerma c'è ancora...
ecco il file:
7
op4 AND 10
op6 OR 80
op3 OR 40
op1 OR 60
op7 AND 50
op2 AND 30
op5 OR 20
op4 op5 //qui è dove il programma da il Segmentation Fault
op2 op5
op3 op7
op1 op4
op5 op7
op4 op6
op2 op4
grazie mille a tutti... siete disponibilissimi! :)
trallallero
30-06-2006, 09:39
il problema é questa riga: op7 AND 50
in particolare op7
praticamente quando fai
op_tmp = nome_tmp[2] - '0';
corrisponde a op_tmp = 7
quindi
strncpy(operazioni[op_tmp].nome, nome_tmp, strlen(nome_tmp));
sfora l'array di Operazioni il che compromette tutta la memoria successiva
Ciao :)
Gandalf_BD
30-06-2006, 09:50
:doh: :doh: :doh:
che errore da pollo :muro: :muro:
grazie mille, ma hai salvato il weekend! :D
:cincin: :mano: :friend: :vicini:
ps: pura curiosità... come mai il segmentation fault non me lo dava al momento dell'invasione di altra memoria?
trallallero
30-06-2006, 10:02
:doh: :doh: :doh:
che errore da pollo :muro: :muro:
sono quelli gli errori peggiori ;) ed é proprio li che serve un altro occhio
che la vede da un altro punto di vista :)
grazie mille, ma hai salvato il weekend! :D
:cincin: :mano: :friend: :vicini:
prima o poi anche tu mi servirai a qualcosa :read: :D
ps: pura curiosità... come mai il segmentation fault non me lo dava al momento dell'invasione di altra memoria?
non lo so. So solo che quando succedono 'ste cose la prima
cosa che faccio é spostare l'ordine delle variabili per vedere
se cambia qualcosa ;)
Forse qualcuno piú esperto di me ti saprá rispondere ....
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.