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

C语言实现LeetCode目标解析器时单行代码触发堆缓冲区溢出

C语言实现字符串解析触发堆缓冲区溢出问题排查

核心错误点

你的代码存在4个会触发未定义行为/内存越界的问题,本地运行正常只是内存环境巧合,在线判题沙箱开启了严格的内存越界检测就会直接崩溃:

  • sizeof无法计算传入函数的字符串长度
    command是函数形参,类型为字符指针,sizeof(command)得到的是指针本身的占用空间(64位系统固定为8字节,32位系统固定为4字节),和传入字符串的实际长度完全无关。当测试用例长度超过这个值时,循环要么提前终止,要么越界读取非法内存。正确获取C字符串长度的方式是调用strlen(command),需要引入头文件<string.h>。
  • 循环步进逻辑缺失,未跳过已匹配的子串
    当前循环每次固定让i自增1,匹配到组合子串后没有跳过后续已识别的字符:匹配()时,i在(位置处理完后,下一轮会落到)字符上,这个字符既不是G也不是(,会导致逻辑混乱;匹配(al)时同理,后续的a/l/)都会被当成新的判断起点,写入ret数组时很容易越界。
  • 内存重分配时未预留字符串结束符空间
    最后调用realloc时传入的大小是counter * sizeof(char),但C语言字符串需要额外1字节存储末尾的\0结束符,分配空间不足会直接触发堆溢出。
  • (al)分支注释状态下属于典型未定义行为
    注释掉ret[counter] = 'a'时,分支仅给ret[counter+1]赋值了'l',ret[counter]位置是malloc申请到的内存里的随机垃圾值,本地运行能出正确结果只是内存残留值刚好符合预期,不代表代码逻辑正确。

修正后可运行代码

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

char * interpret(char * command){
    // 输入最长100字符,输出最长不超过100,多留1字节存结束符
    char * ret = malloc(sizeof(char) * 101);
    int counter = 0;
    int cmd_len = strlen(command);
    for(int i = 0; i < cmd_len; i++)
    {
        if(command[i] == 'G')
        {
            ret[counter++] = 'G';
        }
        else if(command[i] == '(')
        {
            if (command[i + 1] == ')')
            {
                ret[counter++] = 'o';
                i++; // 跳过已匹配的右括号
            }
            else
            {
                ret[counter++] = 'a';
                ret[counter++] = 'l';
                i += 3; // 跳过'al)'三个已匹配字符
            }
        }
        ret[counter] = '\0';
    }
    // 分配空间包含结束符位置
    return realloc(ret, (counter + 1) * sizeof(char));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:45:33