2017-06-26 50 views
-2

我得到一個「*錯誤在`./chatty':munmap_chunk():無效指針:0x000000000040635f *」每當我調試這段代碼(在交換機的情況下REGISTER_OP後),在「free(replySnd)」的調用下,在我粘貼在下面的代碼片段的末尾(從底部開始第12行),我只是不明白爲什麼它發生,因爲指針不應該是靜態的因爲我使用的是strdup(我已經嘗試使用malloc分配內存,然後將內容複製到它中,結果相同)核心轉儲免費通話

我粘貼了整個函數,以便您可以查看每次使用變量replySnd,我發佈了setHeader和setData函數的定義。

我注意到,我導致一個核心轉儲執行任何這些免費的,而不是隻有第一個。

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功能代碼:

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功能:

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; 
} 

我花了太多的時間試圖找到這個bug

+0

選擇LANGUAG。如果它是C,你可以擺脫那些石膏 –

+0

解決這些問題的正確工具是你的調試器。在*堆棧溢出問題之前,您應該逐行執行您的代碼。如需更多幫助,請閱讀[如何調試小程序(由Eric Lippert撰寫)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。至少,你應該[編輯]你的問題,以包含一個[Minimal,Complete,and Verifiable](http://stackoverflow.com/help/mcve)例子來重現你的問題,以及你在調試器中所做的觀察。 –

+0

使用[valgrind](http://www.valgrind.org),你會很快發現問題。 –

回答

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

初始化錯誤號碼(比你需要的時間短)的字節。你不想分配指針的大小,但結構的大小:你想:

reply = malloc(sizeof(message_t)); 

或以確保尺寸的數據相匹配:

reply = malloc(sizeof *reply); 
+1

或者更好,'malloc(sizeof * reply)'。 –

+0

@IharobAlAsimi經典。我編輯採取您的建議帳戶 –

+0

哦,上帝,我沒有注意到我把一個「*」在那裏,檢查它是否現在工作,謝謝 – NokiStrawby

0

當您的程序在調用free時崩潰,這是您代碼中其他地方內存管理不佳的跡象。

在你的情況,問題是這一行:

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

一個指針類型的大小不一定是(事實上,它通常不是),它指向的類型的大小。您使用分配的內存reply,並且它在使用它時不會崩潰(即使此時它肯定是未定義的行爲),並且當您嘗試釋放它時最終崩潰。

正確的分配大小爲:

sizeof(message_t); 

此外,don't cast the result of malloc.