免费通话核心转储

时间:2017-06-26 16:01:23

标签: c memory free dump

我在`./chatty' ;: munmap_chunk()中得到一个" *错误:无效指针:0x000000000040635f * "每当我调试这段代码时(在交换机上的REGISTER_OP之后),在#34; 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;
} 

我花了太多时间试图找到这个错误

2 个答案:

答案 0 :(得分:1)

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

初始化错误的数字(比你需要的短)字节。你不想分配指针的大小,但要分配结构的大小:你想:

reply = malloc(sizeof(message_t));

或确保大小与数据匹配:

reply = malloc(sizeof *reply);

答案 1 :(得分:0)

当你的程序在调用free时崩溃,这表明代码中其他地方的内存管理不佳。

在你的情况下,问题是这一行:

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

指向类型的指针的大小不一定(事实上,它通常不是它指向的类型的大小)。你为reply使用分配的内存,当你使用它时它不会崩溃(即使它在那时肯定是未定义的行为),并且当你试图释放它时最终崩溃

正确的分配大小是:

sizeof(message_t);

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