Newsgroup: it.comp.lang.c
Titolo: Problema malloc?

Salve a tutti. Dopo aver perso quasi due settimane dietro questo
Segmentation Fault, ho deciso di chiedere a voi "maestri" di mostrarmi
la luce...
common.h:
ho definito questa struct come globale
#define NUMPARAM 5
typedef struct 
{
   short client;
   int intervallo;
   char *mail[NUMPARAM];
} strConf;
strConf *Conf;
main.c:
Definisco Conf nella main()
Conf = malloc(sizeof(strConf));
e da qui chiamo una funzione che riempie questa struttura leggendo i
parametri da un file.
Ecco la funzione:
void ChangeConf (int param, char * value)
{
   if (Conf->mail[param] != NULL)
       Conf->mail[param] = realloc(Conf->mail[param],
strlen(value)+1);
   else
       Conf->mail[param] = malloc(strlen(value)+1);
   if ( Conf->mail[param] == NULL ) Error("ChangeConf");
   strncpy(Conf->mail[param], value, strlen(value));
   Conf->mail[param][strlen(value)] = '\0';
}
E fino a qui (per me) tutto bene...
Proseguendo, chiamo la funzione gethostbyname in questo modo
mail.c:
struct hostent *he;
he = gethostbyname (Conf->mail[smtp]);
e qui và in Segmentation fault all'interno della gethostbyname,
esattamente con questo messaggio, catturato con il debugger:
"Program received signal SIGSEGV, Segmentation fault.
0x411577dd in malloc() from /lib/i686/libc.so.6"
quindi il problema mi sembra derivante dal malloc all'interno di
gethostbyname.
Il parametro Conf->mail[smtp] è uguale a "localhost".
Forse ho incasinato qualcosa nelle tabelle di malloc, boh...
Grazie per l'aiuto.
Paolo.

 he = gethostbyname (Conf->mail[smtp]);
-- 
Per l'e-mail rimuovere la frase in maiuscolo e gli underscore.

>        Conf->mail[param] = malloc(strlen(value)+1);
Quell`if() e` inutile, realloc(NULL, size) e` semanticamente identico a
malloc(size):
(manpage di malloc(3))
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,
the call is equivalent to malloc(size);
Quindi basta impostare Conf->mail[param] a NULL all`inizio e poi
chiamare sempre realloc().
Ciao :)
-- 
<@void> Guarda a kickarlo mi sentirei come se stessi picchiando un bambino che caga
<@Pikkio> ti sporcheresti le mani
<@void> Non te lo pulisci il sedere ?
<@Pikkio> no, ho la faccia come il culo

 chiamare sempre realloc().
Grazie per la risposta, credevo che una malloc/realloc su un puntatore
mai inizializzato fosse sufficiente.
Ok, ecco cosa ho fatto:
-----------------------------------------------------------------
void ChangeConf (int param, char * value)
{
   Conf->mail[param] = NULL;
 
   Conf->mail[param] = realloc(Conf->mail[param],strlen(value)+1);
   if ( Conf->mail[param] == NULL ) Error("ChangeConf");
   strncpy(Conf->mail[param], value, strlen(value));
   Conf->mail[param][strlen(value)] = '\0';
}
-----------------------------------------------------------------
purtroppo il risultato non cambia. Inoltre non capisco perché l'errore
si presenta sulla malloc interna della gethostbyname, che quest'ultima
utilizza per allocare "struct hostent *he". Ho provato a utilizzare la
malloc prima della gethostbyname e funziona correttamente.
Grazie per il vostro tempo...
Ciao, Paolo.

 -----------------------------------------------------------------
Ancora peggio.
Devi impostare a NULL _tutti_ gli elementi di mail prima di fare qualsiasi 
altra cosa:
/*Questa funzione viene chiamata prima di utilizzare per
*la prima volta Conf
*/
void init_Conf(void)
{
int i;
for(i=0; i<=NUMPARAM; i++) Conf->mail[i]=NULL;
}
/*Riscrivi ChangeConf cosě:*/
void ChangeConf(int param, char *value)
{
if((Conf->mail[param] = realloc(Conf->mail[param],strlen(value)+1))==NULL)
        Error("ChangeConf");
strncpy(Conf->mail[param], value, strlen(value)+1);/**/
/*strncpy() copia anche il carattere nullo.*/
}
Saluti
-- 
Per l'e-mail rimuovere la frase in maiuscolo e gli underscore.
Worship Him! 666

 malloc(size):
[...]
I puntatori contenuti in Conf->mail non sono stati inizializzati a NULL da 
nessuna parte, quindi contiene un valore indefinito, che non è detto sia 
NULL.
Saluti
-- 
Per l'e-mail rimuovere la frase in maiuscolo e gli underscore.
Worship Him! 666

chiamare sempre realloc().
No: deve impostare a NULL ogni elemento di mail all'inizio del sorgente; 
per fare come dici tu, sarebbe stato più corretto, anche se non era ciò che 
avrebbe voluto, fare free(Conf->mail[param]) e poi una malloc.


 avrebbe voluto, fare free(Conf->mail[param]) e poi una malloc.
Ho inserito questo nella main, subito dopo la malloc:
----------------------------------------------------------------------------
for (i=0;i<NUMPARAM;i++) Conf->mail[i] = NULL;
----------------------------------------------------------------------------
e modificato in questo modo la ChangeConf:
----------------------------------------------------------------------------
void ChangeConf (int param, char * value)
{
   Conf->mail[param] = realloc(Conf->mail[param],strlen(value)+1);
   if ( Conf->mail[param] == NULL ) Error("ChangeConf");
   strncpy(Conf->mail[param], value, strlen(value));
   Conf->mail[param][strlen(value)] = '\0';
}
----------------------------------------------------------------------------
Scusa ma ho preferito lasciare l'if e l'aggiunta del terminatore in
questo
modo, mi sembra più leggibile.
Purtroppo l'errore persiste.
Allego il debug del programma e il seguente SIGSEGV.
Giusto per chiarire cosa fà tutto questo codice:
1) Legge le opzioni da un file e le salva in Conf.
2) Le visualizza a video.
3) Aspetta un input dall'utente.
4) Lo memorizza in Cmd->CmdString e lo "dovrebbe" spedire per mail, se
solo riuscisse a passare la gethostbyname. Nota: se non passo per la
gethostbyname, tutto funziona.
Grazie ancora per il vostro tempo, non sò più cosa fare :(
le righe che iniziano con 1: indicano l'indirizzo di memoria e il
valore
istantaneo della variabile Conf->mail[param] all'interno della
funzione
ChangeConf, dove ho messo il breakpoint.0
--- Debug -----------------------------------------------------------------
Breakpoint 1, ChangeConf (param=0, value=0x804c818 "localhost") at
util.c:34
34        Conf->mail[param] = realloc (Conf->mail[param], strlen
(value) + 1);
1: Conf->mail[param] = 0x0
(gdb) n
35        if (Conf->mail[param] == NULL)
1: Conf->mail[param] = 0x804c688 " \026 @ \026 @acle\021"
(gdb)
38        strncpy (Conf->mail[param], value, strlen (value));
1: Conf->mail[param] = 0x804c688 " \026 @ \026 @acle\021"
(gdb)
39        Conf->mail[param][strlen (value)] = '\0';
1: Conf->mail[param] = 0x804c688 "localhostcle\021"
(gdb)
40      }
1: Conf->mail[param] = 0x804c688 "localhost"
(gdb) c
Continuing.
Breakpoint 1, ChangeConf (param=1, value=0x804c818 "oracle") at
util.c:34
34        Conf->mail[param] = realloc (Conf->mail[param], strlen
(value) + 1);
1: Conf->mail[param] = 0x0
(gdb) n
35        if (Conf->mail[param] == NULL)
1: Conf->mail[param] = 0x804c698 "\210\026 @\210\026 @\020"
(gdb)
38        strncpy (Conf->mail[param], value, strlen (value));
1: Conf->mail[param] = 0x804c698 "\210\026 @\210\026 @\020"
(gdb)
39        Conf->mail[param][strlen (value)] = '\0';
1: Conf->mail[param] = 0x804c698 "oracle @\020"
(gdb)
40      }
1: Conf->mail[param] = 0x804c698 "oracle"
(gdb) c
Continuing.
Breakpoint 1, ChangeConf (param=2, value=0x804c818 "password") at
util.c:34
34        Conf->mail[param] = realloc (Conf->mail[param], strlen
(value) + 1);
1: Conf->mail[param] = 0x0
(gdb) n
35        if (Conf->mail[param] == NULL)
1: Conf->mail[param] = 0x804d028 ""
(gdb)
38        strncpy (Conf->mail[param], value, strlen (value));
1: Conf->mail[param] = 0x804d028 ""
(gdb)
39        Conf->mail[param][strlen (value)] = '\0';
1: Conf->mail[param] = 0x804d028 "password"
(gdb)
40      }
1: Conf->mail[param] = 0x804d028 "password"
(gdb) c
Continuing.
Breakpoint 1, ChangeConf (param=3, value=0x804c818 "localhost") at
util.c:34
34        Conf->mail[param] = realloc (Conf->mail[param], strlen
(value) + 1);
1: Conf->mail[param] = 0x0
(gdb) n
35        if (Conf->mail[param] == NULL)
1: Conf->mail[param] = 0x804d038 ""
(gdb)
38        strncpy (Conf->mail[param], value, strlen (value));
1: Conf->mail[param] = 0x804d038 ""
(gdb)
39        Conf->mail[param][strlen (value)] = '\0';
1: Conf->mail[param] = 0x804d038 "localhost"
(gdb)
40      }
1: Conf->mail[param] = 0x804d038 "localhost"
(gdb)
ReadConfFile () at util.c:197
197           line = startline;         /* Reset line pointer */
(gdb) c
Continuing.
Breakpoint 1, ChangeConf (param=4, value=0x804c818 "oracle@localhost")
at util.c:34
34        Conf->mail[param] = realloc (Conf->mail[param], strlen
(value) + 1);
1: Conf->mail[param] = 0x0
(gdb) n
35        if (Conf->mail[param] == NULL)
1: Conf->mail[param] = 0x804d048 ""
(gdb)
38        strncpy (Conf->mail[param], value, strlen (value));
1: Conf->mail[param] = 0x804d048 ""
(gdb)
39        Conf->mail[param][strlen (value)] = '\0';
1: Conf->mail[param] = 0x804d048 "oracle@localhost"
(gdb)
40      }
1: Conf->mail[param] = 0x804d048 "oracle@localhost"
(gdb) c
Continuing.
--- smptsh client ---
pop server: localhost
pop user: oracle
pop password: password
smtp server: localhost
mail: oracle@localhost
mail check (secs): 5
      ^^^^^^^^^^^^
      questa è la stampa della struttura Conf e funziona.
smtpsh> stringa inserita dall'utente.
You typed this builtin: -1
With this parameter/command: stringa inserita dall'utente.
Program received signal SIGSEGV, Segmentation fault.
0x401578f3 in malloc () from /lib/i686/libc.so.6
^^^^^^^^
qui ha beccato la gethostbyname :(
-----------------------------------------------------------------------

   Conf->mail[param][strlen(value)] = '\0';
   Visto in Conf->mail[param] hai allocato un buffer grande abbastanza
per contenere tutti i caratteri value piu` il terminatore, perche` non
fai:
 
   strcpy(Conf->mail[param], value); ?
-- 
S.L.

    strcpy(Conf->mail[param], value); ?
Funziona, ma non risolverebbe il problema. Grazie comunque.

 1: Conf->mail[param] = 0x804d048 "oracle@localhost"
Credo che sbagli nel passare a gethostbyname() una stringa collla @ in 
mezzo; chiedi su it.comp.os.linux.development


 mezzo; chiedi su it.comp.os.linux.development
alla gethostbyname passo solo l'indirizzo dell'SMTP, "localhost".
Comunque HO TROVATO IL PROBLEMA!!!
Guardate cosa avevo scritto in una funzione, chiamata nel flusso ma 
"insospettabile".
------------------------------------------------------------
int
FillKey (char *ptrKey)
{
   int lenKey;
   lenKey = strlen (ptrKey);
   BF_set_key (&strBfKey, lenKey, ptrKey);
   free(ptrKey); <---- Non mi chiedete perché l'ho fatto.
   return (true);
}
-------------------------------------------------------------
Tolta quella "cosa" tutto funziona.
Incredibile comunque che il problema si verificava sulla gethostbyname.
Grazie comunque a tutti per l'impegno, non sapevo piů dove sbattere la 
testa :)
Ciao, Paolo.

Incredibile comunque che il problema si verificava sulla gethostbyname.
"Quella cosa" libera un puntatore a char che deve essere stato
precedentemente allocato da malloc o realloc o calloc;
Sarà, ma mi hanno insegnato che è bene che i vettori allocati
dinamicamente siano deallocati quando non servono più

 
Infatti hai ragione, solo che non è il luogo adatto per liberare un 
puntatore che poi utilizzerò in seguito :)
Ciao.