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

LeetCode最长回文子串代码触发AddressSanitizer堆缓冲区溢出求助

排查LeetCode最长回文子串代码的heap-buffer-overflow错误

错误原因分析

从报错信息和代码逻辑来看,触发heap-buffer-overflow的核心问题有三个:

  1. 未预留字符串终止符空间:C语言中字符串必须以'\0'结尾,你通过malloc(sizeof(char)*(max))分配的内存仅能存储max个字符,没有给终止符留额外字节。调用者读取返回的字符串时,会越界访问到内存分配区域之外的地址,直接触发溢出错误。
  2. 回文长度计算逻辑错误:你的t变量统计的是双向匹配的步数,并非回文的实际长度。比如对于回文"aba",t会被计算为2,但实际长度是3,这导致max值偏小,后续复制字符时会遗漏部分内容,同时加剧了内存越界风险。
  3. 边界场景未处理:当输入字符串为空或所有字符互不重复时,max会保持0,此时malloc(0)属于未定义行为,同样会引发错误。

解决思路与代码修正

核心修正点

  • 内存分配时多预留1字节,用于存储字符串终止符'\0'。
  • 调整回文长度的计算逻辑,确保max_len是回文的真实长度。
  • 处理空字符串、单字符等边界场景。
  • 复制完字符后必须手动添加'\0'。

基于中心扩展法的优化代码

中心扩展法是解决最长回文子串问题的高效方案,逻辑更清晰,也能避免原代码中的匹配逻辑漏洞:

char * longestPalindrome(char * s){
    int le = strlen(s);
    if (le == 0) {
        char *ans = malloc(1);
        ans[0] = '\0';
        return ans;
    }
    int start = 0, end = 0;

    // 遍历每个可能的中心,分别处理奇数/偶数长度回文
    for (int i = 0; i < le; i++) {
        int len_odd = expandAroundCenter(s, i, i);
        int len_even = expandAroundCenter(s, i, i + 1);
        int max_current = len_odd > len_even ? len_odd : len_even;
        
        // 更新最长回文的边界
        if (max_current > end - start) {
            start = i - (max_current - 1) / 2;
            end = i + max_current / 2;
        }
    }

    int max_len = end - start + 1;
    char *ans = malloc(sizeof(char) * (max_len + 1)); // +1 预留终止符空间
    for (int i = 0; i < max_len; i++) {
        ans[i] = s[start + i];
    }
    ans[max_len] = '\0'; // 添加字符串终止符
    return ans;
}

// 辅助函数:从中心向两侧扩展,计算回文长度
int expandAroundCenter(char *s, int left, int right) {
    int le = strlen(s);
    while (left >= 0 && right < le && s[left] == s[right]) {
        left--;
        right++;
    }
    return right - left - 1;
}

原代码的最小修改版本

如果想保留原代码的双层循环逻辑,只需修正长度计算和内存分配:

char * longestPalindrome(char * s){
    int le = strlen(s);
    if (le == 0) {
        char *ans = malloc(1);
        ans[0] = '\0';
        return ans;
    }
    int start = 0, end = 0;
    int max_len = 1; // 至少存在单字符回文

    for (int i = 0; i < le; i++){
        for (int j = le-1; j > i; j--){
            int temp_i = i;
            int temp_j = j;
            // 检查当前i到j的子串是否为回文
            while (temp_i <= temp_j && s[temp_i] == s[temp_j]){
                temp_i++;
                temp_j--;
            }
            // 确认是回文后,更新最长回文信息
            if (temp_i > temp_j) {
                int current_len = j - i + 1;
                if (current_len > max_len) {
                    max_len = current_len;
                    start = i;
                    end = j;
                }
                break; // 找到以i为起点的最长回文,无需继续遍历更短的j
            }
        }
    }

    char *ans = malloc(sizeof(char)*(max_len + 1));
    for(int i = 0; i < max_len; i++){
        ans[i] = s[start+i];
    }
    ans[max_len] = '\0';
    return ans;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 11:31:06