我在`./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;
}
我花了太多时间试图找到这个错误
答案 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);