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

C语言中unsigned char循环超过127次时出现内存泄漏求助

分析unsigned char循环值≥128时的内存泄漏问题

问题根源定位

先看Valgrind的泄漏报告,明确泄漏来自letter_frequencies函数里的malloc调用。咱们直接拆解这个函数的问题:

size_t *letter_frequencies(char *str) {
    size_t *frequencies = malloc(sizeof(size_t) * 26); // 分配了26个size_t的内存
    for (int i = 0; i < 26; i++) frequencies[i] = 0;
    while (*str) {
        if (!isascii((unsigned char)*str)) return NULL; // 这里直接返回,内存没释放!
        if (isalpha(*str)) frequencies[tolower(*str) - 'a']++;
        str++;
    }
    return frequencies;
}

当检测到非ASCII字符时,函数直接返回NULL,但之前通过malloc申请的frequencies内存完全没被释放——这就是泄漏的直接原因。

那为什么只有c≥128时才会触发?这和字符的符号特性有关:

  • 你的xor_against_key中,str[i]是有符号char类型(默认范围-128~127),而key是unsigned char(0~255)。
  • 原bytes数组的内容是十六进制转换来的,所有字节最高位都是0(比如0x1b、0x37),也就是都在0~127范围内。当c≥128时,它的最高位是1,和原字节异或后,结果的最高位会变成1,对应的有符号char就是负数(比如0^128=128,作为有符号char就是-128)。
  • 传给isascii时,这个负数被转成unsigned char就是128255,超出了`isascii`识别的0127范围,于是触发return NULL,内存泄漏就此发生。
  • 而c<128时,异或结果的最高位还是0,对应字符在0~127范围内,不会触发提前返回,frequencies能被正常free,所以没有泄漏。

修复方案

只需要在letter_frequencies函数返回NULL前,先释放已经申请的内存,同时补上几个细节优化:

size_t *letter_frequencies(char *str) {
    size_t *frequencies = malloc(sizeof(size_t) * 26);
    if (!frequencies) { // 增加malloc失败的容错
        return NULL;
    }
    for (int i = 0; i < 26; i++) frequencies[i] = 0;
    while (*str) {
        if (!isascii((unsigned char)*str)) {
            free(frequencies); // 返回前释放内存
            return NULL;
        }
        // 把char转成unsigned char再传给isalpha/tolower,避免负数导致未定义行为
        if (isalpha((unsigned char)*str)) {
            frequencies[tolower((unsigned char)*str) - 'a']++;
        }
        str++;
    }
    return frequencies;
}

验证说明

修复后再用Valgrind检测,你会发现所有内存都被正常释放:

  • 当循环c到255时,即使触发非ASCII检测,frequencies也会被提前释放,不会留下泄漏。
  • 之前观察到的"c≥128时每次循环漏一块内存"的现象会完全消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:24:38