多线程C程序Valgrind检测出内存块丢失问题求助
内存泄漏原因及修复方案
核心问题
泄漏的根源是你在循环开头malloc的SyncQueueAnswer指针,被dequeue(sq, &sqa)函数修改覆盖,导致原内存地址丢失,无法被释放。
你当前的逻辑是:
- 先分配一块
SyncQueueAnswer内存,把地址存在sqa里 - 调用
dequeue时传入&sqa(即指针的指针) - 如果
dequeue的实现是将队列中已分配好的SyncQueueAnswer对象的地址赋值给sqa,那你第一步malloc的内存地址就被彻底覆盖了——没有任何变量保存原地址,自然永远无法free,每循环一次就泄漏一块内存,这和你观察到的"文件数量增加,丢失块数上升"完全吻合。
修复方案
根据dequeue的设计逻辑,分两种情况处理:
情况1:dequeue用于填充外部预先分配的结构体
如果dequeue的设计是向你预先分配好的sqa结构体中填充filedata和over字段,那你需要修改dequeue的调用方式,不要传指针的指针,直接传结构体指针:
void *threadWorker(void *arg) { SyncQueue *sq = (SyncQueue *)arg; while (1) { SyncQueueAnswer *sqa = malloc(sizeof(SyncQueueAnswer)); if (sqa == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(EXIT_FAILURE); } sqa->filedata = NULL; sqa->over = 0; // 修改这里:传sqa而非&sqa,让dequeue填充已分配的结构体 dequeue(sq, sqa); if (sqa->over == 1 || sqa->filedata == NULL) { free(sqa); pthread_exit((void *)1); } else { calculateFileData(sqa->filedata); pthread_mutex_lock(&send_mutex); if (sendThroughSocket(sqa->filedata, sq->sockfd) < 0) { perror("Error while sending data from thread"); } pthread_mutex_unlock(&send_mutex); free(sqa->filedata->vector); free(sqa->filedata); } free(sqa); } }
同时需要对应修改dequeue的函数签名,比如:
void dequeue(SyncQueue *sq, SyncQueueAnswer *sqa);
情况2:dequeue返回队列中已分配的对象
如果dequeue的设计是从队列取出已分配好的SyncQueueAnswer对象,那你完全不需要在循环开头malloc——队列里的元素已经是分配好的:
void *threadWorker(void *arg) { SyncQueue *sq = (SyncQueue *)arg; while (1) { SyncQueueAnswer *sqa = NULL; // 直接从队列获取已分配的对象 dequeue(sq, &sqa); if (sqa == NULL) { fprintf(stderr, "Dequeue failed\n"); pthread_exit((void *)1); } if (sqa->over == 1 || sqa->filedata == NULL) { free(sqa); pthread_exit((void *)1); } else { calculateFileData(sqa->filedata); pthread_mutex_lock(&send_mutex); if (sendThroughSocket(sqa->filedata, sq->sockfd) < 0) { perror("Error while sending data from thread"); } pthread_mutex_unlock(&send_mutex); free(sqa->filedata->vector); free(sqa->filedata); } free(sqa); } }
额外验证
你可以打印malloc后的sqa地址,以及dequeue后的sqa地址,如果两者不同,就完全验证了指针被覆盖的问题。
内容的提问来源于stack exchange,提问作者mike
相关产品推荐
相关产品推荐

