Newsgroup: it.comp.os.linux.development
Titolo: Ricercare un errore per la malloc

Salve NG,
Ho un programma che carica dei messaggi di errore da un file e li memorizza
in una lista concatenata. Qui' pero' temo di aver fatto qualche casino,
perche' piu' avanti nel programma la chiamata a malloc mi crea questo:
se faccio: malloc(12) tutto Ok
se faccio: malloc(13) mi va in segmentation fault
Non ho capito da cosa potrebbe dipendere, non credo di aver esaurito la
memoria. Cosa posso guardare?
Questo e' la funzione incriminata:
int CaricaAllarmi()  {
        sigset_t blk;
        sigset_t sigsv;
        struct lista  {
                char *str;
                struct lista *next;
        }*basenewl,*newl,*tmp,*prev;
        char buffer[2048];
        int count = 0;
        FILE *FTestiAllarmi;
        // Provo ad aprire il file
        if ((FTestiAllarmi = fopen("testiallarmi.txt","r")) == NULL)  {
                return(-1);
        }
 
        // Blocco i segnali per evitare problemi con la malloc
        sigemptyset(&blk);
        sigaddset(&blk,SIGINT);
        sigprocmask(SIG_BLOCK,&blk,&sigsv);
        newl=(struct lista *) malloc(sizeof(struct lista));
        // Memorizzo il primo indirizzo per poterlo usare dopo
        basenewl = newl;
        // Legge il file
        while(fgets(buffer, sizeof buffer,FTestiAllarmi)) {
                if(buffer[0] != '\n')  {
                   count++;
                   // Copia una riga nella struttura
                   newl->str = strdup(buffer);
                   if(newl->str == NULL)  {
                        fputs("strdup\n", stderr);
                        return(-1);
                   }
                   // Alloca lo spazio nello heap per newl
                   newl->next =(struct lista *) malloc(sizeof(struct lista));
                   if(newl->next == NULL)  {
                        perror("malloc");
                        return(-1);
                   }
                   // Ricordo l'indirizzo attuale
                   prev=newl;
                   // Punto al nuovo indirizzo
                   newl=newl->next;
                }
        }
        fclose(FTestiAllarmi);
        // L'ultima deve avere next che punta a NULL
        newl->next = NULL;
        // E soprattuto la penultima di cui poi controllo newl->next
        prev->next= NULL;
        // Ora imposto newl sulla prima struttura.
        newl=basenewl;
        // Alloco la memoria per TestoAllarme
        TestoAllarme = malloc(sizeof(char *) * (count+1));
        if(TestoAllarme == NULL)  {
                perror("malloc");
                return(-1);
        }
        // Ricordo che poi devo deallocare la memoria.
        atexit(ScaricaAllarmi);
        // Memorizza le stringhe e libera newl
        while(newl)  {
                *TestoAllarme++ = newl->str;
                tmp = newl;
                newl = newl->next;
                free(tmp);
        }
        // Imposta all'inizio l'TestoAllarme
        // D'ora in poi copiarlo sempre, non usarlo
        // direttamante altrimenti si sposta l'indirizzo
        TestoAllarme -=  (count);
 
        // Riabilita sigint
        sigprocmask(SIG_SETMASK,&sigsv,0);
        return(0);
}
Grazie, Nicola.
-- 
chi va pian va san e va lontan

         atexit(ScaricaAllarmi);
Ti posto quello che ho scritto. Ripeto, non mi ha dato alcun errore.
Ah, ho modificato il valore di return della CaricaAllarmi in modo che
ritorni count.
E ovviamente ho dichiarato TestoAllarme globale per renderlo visibile nel
main.
Ciao,
Ema
--------------------------------------------------
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * * TestoAllarme;
int CaricaAllarmi() {
  sigset_t blk;
  sigset_t sigsv;
  struct lista {
    char *str;
    struct lista *next;
  }*basenewl,*newl,*tmp,*prev;
  char buffer[2048];
  int count = 0;
  FILE *FTestiAllarmi;
  // Provo ad aprire il file
  if ((FTestiAllarmi = fopen("prova2.c","r")) == NULL) {
    return(-1);
  }




  fclose(FTestiAllarmi);

  free(newl);
  // E soprattuto la penultima di cui poi controllo newl->next
  prev->next= NULL;
  // Ora imposto newl sulla prima struttura.
  newl=basenewl;
  // Alloco la memoria per TestoAllarme
  TestoAllarme = malloc(sizeof(char *) * (count+1));
  if(TestoAllarme == NULL) {
    perror("malloc");
    return(-1);
  }
  // Ricordo che poi devo deallocare la memoria.
  //  atexit(ScaricaAllarmi);
  // Memorizza le stringhe e libera newl
  while(newl) {
    *TestoAllarme++ = newl->str;
    tmp = newl;
    newl = newl->next;
    free(tmp);
  }
  // Imposta all'inizio l'TestoAllarme
  // D'ora in poi copiarlo sempre, non usarlo
  // direttamante altrimenti si sposta l'indirizzo
  TestoAllarme -=  (count);
  // Riabilita sigint
  sigprocmask(SIG_SETMASK,&sigsv,0);
  return count;
}
int main(void) {
  int cnt, i;
  cnt =  CaricaAllarmi();
  for (i=0; i<cnt; i++)
    printf("%s",TestoAllarme[i]);
  return 0;
}
------------------------------------------------


Prova a debuggare il programma dopo averlo linkato con le librerie "electric
fence" (-lefence).
http://www.die.net/doc/linux/man/man3/efence.3.html
Alessandro.

 memoria. Cosa posso guardare?
man malloc, guarda le note dove si parla di "MALLOC_CHECK_", sperando che tu
usi una versione recente della libc (5.4.23 o superiore).
Ciao,
-- 
       Roberto Divia`             Love at first sight is one of the greatest
       =============             labour-saving devices the world has ever seen.
Mailbox: C02110                 CERN-European Organization for Nuclear Research
E-mail: 
Robert...@cern.ch
           CH-1211 GENEVE 23, Switzerland

 tu usi una versione recente della libc (5.4.23 o superiore).
Se la data della man page e' quella dell'ultimo aggiornamento credo proprio
di si. Ho una rh9.0
Dopo aver provato a compilare con MALLOC_CHECK_=0,1 e 2 non mi chrasha piu'
il programma :O Allora ho cancellato la variabile MALLOC_CHECK_ (ho aperto
un altro xterm) e il problema si ripresenta. 
Non ho ben capito la funzione di MALLOC_CHECK_, ma mi pare che si limiti a
ignorare l'errore in attesa che il mio programma vada a scassare qualche
area di memoria che dovrebbe lasciare stare ???


test wrote:

Questo e' interessante, l'errore e' apparso da un'altra parte (prima). Non
capisco perche' nei miei libri questa libreria non e' citata (risale al
93!).
Ora faccio qualche test.


 ritorni count.
Questa e' una buona idea :)
cut...


 area di memoria che dovrebbe lasciare stare ???
Potrebbe esserci una condizione di conflitto dinamico, non sarebbe la prima
volta. Il tuo processo interagisce con altri processi? O con la rete? In
effetti, la MALLOCK_CHECK e` un implementazione diversa della stessa
libreria. E` possibile che il tuo codice scriva dove non dovrebbe (tipico di
un ri-utilizzo di un blocco ritornato) e che questo mandi una libreria nel
pallone ma non l'altra... In questo caso devi controllare tutte le free() e
verificare che _tutte le copie_ dei puntatori liberati vengano invalidate.


 vengano invalidate.
Il mio processo interagisce con altri processi, e di sicuro scrivo dove non
devo scrivere. Ora sto' riguardando tutto il codice :P
