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

返回字符串时触发heap-buffer-overflow运行时错误的排查

反转字符串单词时触发heap-buffer-overflow错误的排查与修复

问题背景

编写了用于反转字符串中每个单词的C语言函数reverseWords,编译运行时触发heap-buffer-overflow错误,推测问题出在if (res[i] == ' ') break;行。原始代码如下:

char * reverseWords(char * s){    
    int n = strlen(s);    
    char *res = malloc(n + 1);    
    strcpy(res,s);    
    char temp[100];    
    int i = 0;    
    int j = 0;    
    for (i = 0; i < n; i++){        
        for (j = 0; j < n; j++, i++){            
            if (res[i] == ' ') break;            
            temp[j] = res[i];        
        }        
        while (j > 0){            
            j--;            
            res[i - j - 1] = temp[j];        
        }    
    }    
    return res;
}

运行时错误日志:

==30==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000005c at pc 0x5620553333a3 bp 0x7ffde02da850 sp 0x7ffde02da840
READ of size 1 at 0x60300000005c thread T0
    #2 0x7f359ea9c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
0x60300000005c is located 0 bytes to the right of 28-byte region [0x603000000040,0x60300000005c)
allocated by thread T0 here:
    #0 0x7f359f6e1bc8 in malloc (/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
    #3 0x7f359ea9c0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
Shadow bytes around the buggy address:
  0x0c067fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0c067fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0c067fff8000: fa fa 00 00 00 04 fa fa 00 00 00[04]fa fa fa fa
  0x0c067fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c067fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
  Shadow gap:              cc
==30==ABORTING

错误原因分析

  • 越界访问问题:内层for循环中,i持续自增直到遇到空格,但未判断i是否超出字符串长度n。处理最后一个单词时,循环会执行到i = n,此时访问res[i]会越界,触发heap-buffer-overflow。
  • temp数组溢出风险:定义temp[100]固定长度,若原字符串中有超过100字符的单词,会导致栈溢出。
  • 外层循环的i重复自增:外层for循环每次会让i++,但内层循环已经对i进行了多次自增,导致外层循环的i跳过部分字符,逻辑混乱。

修复后的代码

char * reverseWords(char * s) {
    int n = strlen(s);
    char *res = malloc(n + 1);
    if (!res) return NULL; // 检查malloc是否成功
    strcpy(res, s);
    
    int start = 0;
    for (int i = 0; i <= n; i++) {
        // 遇到空格或字符串结尾时,反转当前单词
        if (res[i] == ' ' || i == n) {
            int end = i - 1;
            // 原地反转单词,无需额外temp数组
            while (start < end) {
                char temp = res[start];
                res[start] = res[end];
                res[end] = temp;
                start++;
                end--;
            }
            start = i + 1; // 移动到下一个单词的起始位置
        }
    }
    return res;
}

修复说明

  • 避免越界访问:循环条件改为i <= n,当i == n时处理最后一个单词,同时在判断空格前先检查i是否到达字符串末尾。
  • 原地反转优化:去掉固定长度的temp数组,直接在res中交换字符完成反转,避免栈溢出风险。
  • 修正索引逻辑:使用start变量记录每个单词的起始位置,避免内外层循环对i的重复修改,逻辑更清晰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 16:46:09