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

自定义free函数未完全释放内存,Valgrind报告‘still reachable’问题求助

自定义free函数未完全释放内存,Valgrind报告‘still reachable’问题求助

各位好,我最近跟着一篇文章实现了简化版的malloc和free,想通过Valgrind验证正确性,于是在两个函数里分别加了VALGRIND_MALLOCLIKE_BLOCK(block, size, 0, 0);和VALGRIND_FREELIKE_BLOCK(block, 0);。Valgrind确实能正确追踪内存分配动作,但程序退出时总有一个块被标记为still reachable,具体的Valgrind输出如下:

HEAP SUMMARY:
==74425== in use at exit: 20 bytes in 1 blocks
==74425== total heap usage: 2 allocs, 2 frees, 1,044 bytes allocated
==74425==
==74425== 20 bytes in 1 blocks are still reachable in loss record 1 of 1
==74425==
==74425== LEAK SUMMARY:
==74425== definitely lost: 0 bytes in 0 blocks
==74425== indirectly lost: 0 bytes in 0 blocks
==74425== possibly lost: 0 bytes in 0 blocks
==74425== still reachable: 20 bytes in 1 blocks
==74425== suppressed: 0 bytes in 0 blocks

文章里在union结构体里加了个固定16字节的stub成员,但其实没必要,因为我这边sizeof(header_t)计算出来是24字节。下面是我的核心实现代码:

#include <pthread.h>
#include <unistd.h>
#include <stdio.h>

// 注:header_t的定义在单独头文件中,包含状态union、size、is_free、next等成员
pthread_mutex_t global_malloc_lock;
header_t *head, *tail;

header_t *get_free_block(size_t size) {
    header_t *curr = head;
    while (curr) {
        if (curr->s.is_free && curr->s.size >= size) {
            return curr;
        }
        curr = curr->s.next;
    }
    return NULL;
}

void *my_malloc(size_t size) {
    size_t total_size;
    void *block;
    header_t *header;
    if (!size) {
        return NULL;
    }
    pthread_mutex_lock(&global_malloc_lock);
    header = get_free_block(size);
    if (header) {
        header->s.is_free = 0;
        pthread_mutex_unlock(&global_malloc_lock);
        return (void*)(header+1);
    }
    total_size = sizeof(header_t) + size;
    block = sbrk(total_size);
    if (block == (void*) -1) {
        pthread_mutex_unlock(&global_malloc_lock);
        return NULL;
    }
    header = block;
    header->s.is_free = 0;
    header->s.size = size;
    header->s.next = NULL;
    if (!head) {
        head = header;
    }
    if (tail) {
        tail->s.next = header;
    }
    tail = header;
    pthread_mutex_unlock(&global_malloc_lock);
    VALGRIND_MALLOCLIKE_BLOCK(block, size, 0, 0);
    return (void*)(header+1);
}

void my_free(void* block) {
    header_t *header, *tmp;
    void *programbreak;
    if (!block) {
        return;
    }
    pthread_mutex_lock(&global_malloc_lock);
    header = (header_t*)block - 1;
    programbreak = sbrk(0);
    if ((char*)block + header->s.size == programbreak) {
        if (head == tail) {
            head = tail = NULL;
        } else {
            tmp = head;
            while(tmp) {
                if (tmp->s.next == tail) {
                    tmp->s.next = NULL;
                    tail = tmp;
                }
                tmp = tmp->s.next;
            }
        }
        sbrk(0 - sizeof(header_t) - header->s.size);
        pthread_mutex_unlock(&global_malloc_lock);
        VALGRIND_FREELIKE_BLOCK(block, 0);
        return;
    }
    header->s.is_free = 1;
    pthread_mutex_unlock(&global_malloc_lock);
}

测试用的main函数很简单:

int main(int argc, char const *argv[]) {
    printf("sizeof(header_t) = %zu\n", sizeof(header_t));
    int* block = my_malloc(5*sizeof(int));
    my_free(block);
    return 0;
}

我现在困惑的点是:明明已经调用了my_free(),也用VALGRIND_FREELIKE_BLOCK()告诉Valgrind这块内存被释放了,为什么还是会出现still reachable的标记?是sbrk()没有真正把内存还给系统,还是我的free逻辑里有什么遗漏的地方?

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:48:12