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

使用Capstone时出现大量不可释放内存的问题求助

问题:小 malloc 调用导致 Capstone 内存无法释放

我使用Capstone对/usr/lib/x86_64-linux-gnu/dri/i965_dri.so中7,838,304字节的片段进行反汇编,代码如下:

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <stdlib.h>
#include <capstone/capstone.h>

#define MAX_DISAS_BYTES (0x8e0bb0 - 0x167150)
#define MAX_PATH_LEN 200

unsigned char code [MAX_DISAS_BYTES];

void disas()
{ 
    cs_insn *insns;
    int count;
    unsigned long fileOff = 0x167150;
    unsigned long addrOff = 0x167150;
    unsigned int size = (0x8e0bb0 - 0x167150);
    char fileName [MAX_PATH_LEN] = "/usr/lib/x86_64-linux-gnu/dri/i965_dri.so";
    if (size > (MAX_DISAS_BYTES))
    {
        printf("fn size too large (%d > %d)\n", size , (MAX_DISAS_BYTES));
        exit(1);
    }

    FILE *f = fopen(fileName, "rb");
    if (!f)
    {
        printf("fopen");
        exit(1);
    }

    if (fseek(f, fileOff, SEEK_SET) != 0)
    {
        printf("fseek");
        fclose(f);
        exit(1);
    }

    size_t n = fread(code, 1, MAX_DISAS_BYTES, f);
    fclose(f);

    csh handle;

    if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK)
    {
        fprintf(stderr, "Failed to initialize Capstone\n");
        exit(1);
    }

    // Enable detailed mode
    cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);

    count = cs_disasm(handle, code, size, addrOff, 0, &insns);

    // bad mallocs
    void *m1 = malloc(sizeof(cs_detail));
    void *m2 = malloc(sizeof(cs_detail));
    void *m3 = malloc(sizeof(cs_detail));
    void *m4 = malloc(sizeof(cs_detail));
    void *m5 = malloc(sizeof(cs_detail));
    // end of bad mallocs

    if (count > 0)
    {
        //for (size_t i = 0; i < count; i++)
        //{
        //    printf("0x%"PRIx64":\t%s\t%s\n", insns[i].address, insns[i].mnemonic, insns[i].op_str);
        //}

        printf("to free\n");
        sleep(5);
        cs_free(insns, count);
        printf("freed\n");
        sleep(5);
    }
    else 
    {
        printf("Failed to disassemble bytes at offset 0x%lx\n", fileOff);
        exit(1);
    }

    cs_close(&handle); 
}

int main()
{
    disas();
    return 0;
}

问题详情

添加标记为// bad mallocs的五个malloc()调用后,大量内存变为不可释放状态:

  • 程序执行前,系统RSS为2.8 GB
  • 执行printf("to free\n")时,RSS为6.28 GB
  • 执行printf("freed\n")时,RSS仍有5.86 GB,近3GB内存无法释放

但移除这些malloc调用,或者在调用cs_free()前释放它们,cs_free()就能正常释放额外内存。想知道这几个小的动态分配为何会导致大量内存不可释放。


原因分析

  1. Capstone的内存分配特性:启用CS_OPT_DETAIL模式后,cs_disasm会为大量指令分配详细信息内存,这类大内存通常通过glibc的mmap接口分配(属于"大块内存",一般超过128KB),释放时本可以直接归还给内核。
  2. glibc malloc的内存池机制:小块内存(比如sizeof(cs_detail)这类几十到几百字节的分配)会被放入malloc的用户态内存池,不会立即归还给内核。而且如果小块内存和Capstone的大块内存处于同一段内存区域(比如同一个虚拟内存页组),glibc不会主动合并内存页并归还内核。
  3. 冲突点:你在cs_disasm之后分配的小块malloc,会占用Capstone大块内存所在的部分内存页。当cs_free释放Capstone的内存时,因为这些小块内存还占用着同区域的页,内核无法回收整个大块内存区域,导致RSS居高不下。如果提前释放这些小块malloc,Capstone的大块内存区域就没有被占用,cs_free后glibc就能把整个大块归还给内核,RSS就会正常下降。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.11 23:53:11