You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多线程C程序Valgrind检测出内存块丢失问题求助

内存泄漏原因及修复方案

核心问题

泄漏的根源是你在循环开头malloc的SyncQueueAnswer指针,被dequeue(sq, &sqa)函数修改覆盖,导致原内存地址丢失,无法被释放。

你当前的逻辑是:

  1. 先分配一块SyncQueueAnswer内存,把地址存在sqa里
  2. 调用dequeue时传入&sqa(即指针的指针)
  3. 如果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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 04:35:14