2017-06-26 4 views
-2

Ich erhalte einen "* Fehler in` ./chatty ': munmap_chunk(): ungültige Zeiger: 0x000000000040635f *" wenn ich debuggen dieses Stück Code (nach dem Fall REGISTER_OP am Schalter), beim Aufruf von "free (replySnd)", um das Ende des Stückes Code, das ich unten eingefügt habe ... (12. Reihe von unten), verstehe ich einfach nicht, warum es passiert, da der Zeiger nicht statisch sein sollte wie ich benutze strdup (ich habe bereits versucht, Speicher zuweisen mit malloc und dann kopieren Sie den Inhalt in sie, und das Ergebnis war das gleiche)Core-Dump auf kostenlosen Anruf

Ich klebte die ganze Funktion, so dass Sie einen Blick auf jede Verwendung der haben Variable replySnd, und ich poste die Definition der Funktionen setHeader und setData.

Mir ist aufgefallen, dass ich einen Core-Dump verursache, der irgendeinen von diesen frei ausführt, nicht nur mit dem ersten.

void* workerFunction(void* arg) { 
/* Estraggo i parametri passati */ 
workerparam* params = (workerparam*)arg; 
usertable_t* usrTbl = params->table; 
struct statistics* chatStats = params->stats; 
pthread_mutex_t* statsMux = params->mux; 
size_t maxMsgSize = params->msgSize, maxFileSize = params->fileSize; 
int tmp; 

request_t* req; 
message_t* reply; 

op_t replyOp; 
char* replySnd; 

char* replyRcv; 

char* replyBuf; 
unsigned int replyBufLen; 

userdata_t* tmpUsr; 

int replyFd; 

int nonDeall, toSend; 

printf("Worker: Initialized\n"); 

for (;;) { 
    reply = (message_t*)malloc(sizeof(message_t*)); 
    if(!reply) perror("malloc"); 

    replyBuf = NULL; 
    replyBufLen = 0; 

    toSend = 1; 
    nonDeall = 0; 

    /* Ottengo la richiesta da eseguire */ 
    req = reqPop(); 
    if (!req) perror("reqPop"); 
    printf("Worker: Got a request (OP=%d)\n", req->op); 

    replyFd = req->fd; 


    /* Eseguo un controllo sul tipo di operazione */ 
    switch (req->op) { 
     case REGISTER_OP: { 
      replySnd = ""; 

      if (strlen(req->sname) == 0) { 
       replyRcv = ""; 
       replyOp = OP_FAIL; 
       incErrors(chatStats, statsMux); 
      } else if ((tmp =usertable_isRegistered(usrTbl, (req->sname))) == -1) { 
       replyRcv = ""; 
       perror("isRegistered"); 
       replyOp = OP_FAIL; 
       incErrors(chatStats, statsMux); 
      } else if (tmp == 1) { 
       replyRcv = ""; 
       replyOp = OP_NICK_ALREADY; 
       incErrors(chatStats, statsMux); 
      } else { // Inserisco il nuovo utente 

       replyRcv = strdup(req->sname); 
       tmpUsr = userdata_create(); 
       if(!tmpUsr) perror("userdata_create"); 
       strcpy((tmpUsr->name), (req->sname)); 

       tmpUsr->isOnline = 1; 
       tmpUsr->lastFd = req->fd; 
       usertable_insert(usrTbl, tmpUsr); 


       replyOp = OP_OK; 
       incRegistered(chatStats, statsMux); 
       incOnline(chatStats, statsMux); 

       replyBuf = usertable_getOnlineUsersAsString(usrTbl, &replyBufLen); 
      } 
     } break; 
     case CONNECT_OP: { 
      replySnd = ""; 
      if (strlen(req->sname) == 0) { 
       replyRcv = ""; 
       replyOp = OP_FAIL; 
       incErrors(chatStats, statsMux); 
      } else if ((tmp =usertable_isRegistered(usrTbl, (req->sname))) == -1) { 
       replyRcv = ""; 
       perror("isRegistered"); 
       replyOp = OP_FAIL; 
       incErrors(chatStats, statsMux); 
      } else if (tmp == 0) { 
       replyRcv = ""; 
       replyOp = OP_NICK_UNKNOWN; 
       incErrors(chatStats, statsMux); 
      } else { // Inserisco il nuovo utente 
       replyRcv = strdup(req->sname); 
       if (usertable_setOnline(usrTbl, replyRcv, replyFd) < 0) { 
        perror("setOnline"); 
        replyOp = OP_FAIL; 
        incErrors(chatStats, statsMux); 
       } else { 
        replyOp = OP_OK; 
        incOnline(chatStats, statsMux); 

        replyBuf = usertable_getOnlineUsersAsString(usrTbl, &replyBufLen); 
       } 
      } 

     } break; 
     case POSTTXT_OP: { 
      replySnd = strdup(req->sname); 
      replyRcv = strdup(req->rname); 
      if(!replySnd || !replyRcv || strlen(replySnd) == 0 || strlen(replyRcv) == 0) { 
       replyOp = OP_FAIL; 
      } else if (usertable_isOnline(usrTbl, replySnd) != 1 || usertable_isRegistered(usrTbl, replyRcv) != 1) { 
       replyOp = OP_NICK_UNKNOWN; 
      } else if (req->size > maxMsgSize) { 
       replyOp = OP_MSG_TOOLONG; 
      } else { 
       nonDeall = 1; 
       replyOp = TXT_MESSAGE; 
       replyBuf = strdup(req->msg); 
       replyBufLen = req->size; 
      } 

     } break; 
    } 

    /* Creo il messaggio */ 
    setHeader(&(reply->hdr), replyOp, replySnd); 
    setData(&(reply->data), replyRcv, replyBuf, replyBufLen); 

    if (replyOp == TXT_MESSAGE) { 
     tmp = usertable_addMessage(usrTbl, replyRcv, reply); 
     if (tmp < 0) perror("internal usertable inconsistency"); 
     if (tmp == 0) { /* Receiver Offline */ 
      incTxtNonDel(chatStats, statsMux); 
      toSend = 0; 
     } else { /* Receiver Online */ 
      incTxtDel(chatStats, statsMux); 
      toSend = 1; 
     } 
    } 

    if(toSend) { 
     /* Invio il messaggio */ 
     if (sendResponse(replyFd, reply) < 0) perror("sendResponse"); 
    } 


    if(!nonDeall) { 
     /* Libero la memoria allocata */ 
     free(replySnd);printf("Worker: I GOT HERE snd\n"); 
     free(replyRcv);printf("Worker: I GOT HERE rcv\n"); 
     free(replyBuf);printf("Worker: I GOT HERE buf\n"); 
     free(reply);printf("Worker: I GOT HERE reply\n"); 
    } 

    //TODO Implementare invio, gestione msginviati, sendatata aggiuntivo e deallocamento pointers 
} 

return NULL; 

setHeader Funktionscode:

static inline void setHeader(message_hdr_t *hdr, op_t op, char *sender) { 
#if defined(MAKE_VALGRIND_HAPPY) 
    memset((char*)hdr, 0, sizeof(message_hdr_t)); 
#endif 
    hdr->op = op; 
    strncpy(hdr->sender, sender, strlen(sender)+1); 

} 

setData Funktion:

static inline void setData(message_data_t *data, char *rcv, const char *buf, unsigned int len) { 
#if defined(MAKE_VALGRIND_HAPPY) 
    memset((char*)&(data->hdr), 0, sizeof(message_data_hdr_t)); 
#endif 

    strncpy(data->hdr.receiver, rcv, strlen(rcv)+1); 
    data->hdr.len = len; 
    data->buf  = (char *)buf; 
} 

Ich habe viel zu viele Stunden damit, diesen Fehler finden

+0

die languag wählen. Wenn es C ist, können Sie diese Umwandlungen loswerden –

+0

Das richtige Werkzeug, um solche Probleme zu lösen, ist Ihr Debugger. Sie sollten Schritt für Schritt durch Ihren Code * gehen, bevor Sie auf Stack Overflow nachfragen. Für weitere Hilfe lesen Sie bitte [Wie kleine Programme zu debuggen (von Eric Lippert)] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). Zumindest sollten Sie Ihre Frage so bearbeiten, dass sie ein [minimales, vollständiges und überprüfbares] (http://stackoverflow.com/help/mcve) Beispiel enthält, das Ihr Problem zusammen mit den Beobachtungen, die Sie im Debugger gemacht haben, reproduziert . –

+0

Verwenden Sie [Valgrind] (http://www.valgrind.org), und Sie werden das Problem sehr schnell finden. –

Antwort

1
reply = (message_t*)malloc(sizeof(message_t*)); 

initialisiert die falsche Nummer (kürzer als du brauchst) von Bytes. Sie wollen nicht die Größe des Zeiger aber die Größe der Struktur zuzuordnen: Sie wollen:

reply = malloc(sizeof(message_t)); 

oder um sicherzustellen, dass die Größe der Daten übereinstimmt:

reply = malloc(sizeof *reply); 
+1

zurückgeben Oder viel besser, 'malloc (sizeof * reply)'. –

+0

@IharobAlAsimi ein Klassiker. Ich bearbeitete, um Ihren Vorschlag in Betracht zu ziehen –

+0

oh Gott, ich habe nicht bemerkt, dass ich ein "*" dort gesetzt habe und überprüft habe, ob es jetzt funktioniert, danke – NokiStrawby

0

Wenn Ihr Programm stürzt beim Aufruf free ab Es ist ein Zeichen für schlechte Speicherverwaltung an anderer Stelle in Ihrem Code.

In Ihrem Fall ist das Problem, diese Zeile:

reply = (message_t*)malloc(sizeof(message_t*)); 

Die Größe eines Zeigers auf einen Typ nicht unbedingt (in der Tat, es ist in der Regel nicht) die Größe des Typs verweist er auf . Sie verwenden den zugewiesenen Speicher für reply, und es stürzt nicht ab, während Sie es verwenden (obwohl es zu diesem Zeitpunkt definitiv undefined Verhalten ist), und schließlich abstürzt, wenn Sie versuchen, es zu befreien.

Die korrekte Zuordnung Größe ist:

sizeof(message_t); 

Auch don't cast the result of malloc.