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

已释放calloc内存,C程序仍被Valgrind检测出内存泄漏求助

PCRE正则拆分操作数/运算符的内存泄漏排查

我通过PCRE正则表达式从输入字符串中拆分操作数与运算符,将其作为独立元素存入二维数组。但Valgrind持续提示存在内存泄漏,尽管我已释放所有calloc分配的内存——正则匹配结果从buffer指针复制到raw的分段中,输出后已释放两者。以下是程序代码及Valgrind检测结果,恳请排查泄漏原因:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pcre.h>

int compile_expression(char *raw, char **buffer, int segment_count, int segment_size,
                       char *source, int size, pcre *regex);

int main(void)
{
    char input[100] = {0};
    int input_size;

    fgets(input, 99, stdin);
    input_size = strlen(input);

    // compile regex
    char regex[] = "\(.+\)|\d+\.?\d*|[-+*/^]";
    const char *errptr;
    int erroffset;
    pcre *re = pcre_compile(regex, 0, &errptr, &erroffset, NULL);

    if (re == NULL)
    {
        printf("regex compile error");
        return -1;
    }

    char *raw = calloc(20, 10);
    char **buffer = calloc(20, sizeof(char*));

    if (raw != NULL && buffer != NULL)
    {
        int err;

        err = compile_expression(raw, buffer, 20, 10, input, input_size, re);

        // output
        if (err == 0)
        {
            for (int i = 0; i < 20 && buffer[i] != NULL; i++)
            {
                printf("[ %s ]", buffer[i]);
            }
            printf("\n");
        } else return -1;
    }

    free(buffer);
    free(raw);

    return 0;
}

int compile_expression(char *raw, char **buffer, int segment_count, int segment_size,
                       char *source, int size, pcre *regex)
{
    int result = 1;
    int last_offset = 0;
    char match_buffer[size];
    int ovector[30];

    for (int i = 0; i < segment_count && result == 1; i++)
    {
        result = pcre_exec(regex, NULL, source, size, last_offset, 0, ovector, 30);

        if (result < 0)
            break;
        
        memset(match_buffer, 0, sizeof(match_buffer)); // clear
        strncpy(match_buffer, source + ovector[0], ovector[1] - ovector[0]);

        buffer[i] = raw + segment_size * i;
        strncpy(buffer[i], match_buffer, segment_size - 1);

        last_offset = ovector[1];
    }

    if (result != PCRE_ERROR_NOMATCH && result < 0)
    {
        return -1;
    }
    
    return 0;
}

Valgrind输出:

==28424== 
1 + 1
[ 1 ][ + ][ 1 ]
==28424== 
==28424== HEAP SUMMARY:
==28424==     in use at exit: 122 bytes in 1 blocks
==28424==   total heap usage: 5 allocs, 4 frees, 2,530 bytes allocated
==28424== 
==28424== 122 bytes in 1 blocks are definitely lost in loss record 1 of 1
==28424==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==28424==    by 0x487D70E: pcre_compile2 (in /usr/lib/x86_64-linux-gnu/libpcre.so.3.13.3)
==28424==    by 0x1093A0: main (in /home/canada/VScode-projects/test/test)
==28424== 
==28424== LEAK SUMMARY:
==28424==    definitely lost: 122 bytes in 1 blocks
==28424==    indirectly lost: 0 bytes in 0 blocks
==28424==      possibly lost: 0 bytes in 0 blocks
==28424==    still reachable: 0 bytes in 0 blocks
==28424==         suppressed: 0 bytes in 0 blocks
==28424== 
==28424== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

泄漏原因与修复方案

从Valgrind的调用栈可以明确:泄漏的内存是pcre_compile函数分配的正则表达式对象。你只释放了raw和buffer,但没有调用PCRE库提供的pcre_free函数释放编译后的正则对象re。

修复步骤:

  1. 在free(raw)之后,添加pcre_free(re);,确保释放PCRE分配的内存。
  2. 补充异常分支的内存释放:比如当raw或buffer分配失败时,以及compile_expression调用失败返回时,也要提前调用pcre_free(re),避免泄漏。

修改后的main函数关键部分示例:

free(buffer);
    free(raw);
    pcre_free(re); // 新增:释放PCRE编译的正则对象

    return 0;

同时,在else return -1;分支补充释放:

} else {
            pcre_free(re);
            return -1;
        }

当raw或buffer分配失败时也要释放:

if (raw != NULL && buffer != NULL)
    {
        // ...原有代码
    } else {
        pcre_free(re);
    }

内容的提问来源于stack exchange,提问作者expoodo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 21:47:04