LeetCode 1768题合并字符串时出现AddressSanitizer栈溢出错误求助
LeetCode合并字符串交替问题的栈溢出错误分析
问题概述
给定两个字符串word1和word2,交替添加字符合并字符串,以word1开头。若一个字符串更长,将剩余字符追加到合并字符串末尾,返回合并后的字符串。
测试用例:
word1 = "rlvrpyrhcxbceffrgiy"; word2 = "ktqi";
本地CLion运行正常,但LeetCode提交时触发Runtime Error,错误代码如下:
class Solution { public: string mergeAlternately(string word1, string word2) { string merged; char *p1,*p2; string longstring; if(word1.length() >= word2.length()){ longstring = word1; } else{ longstring = word2; } for (int i = 0; i < longstring.length(); i++) { p1 = &word1[i]; p2 = &word2[i]; if(*p1 != '\0' && *p2 != '\0'){ merged += *p1; merged += *p2; } else if(*p1 != '\0' && *p2 == '\0'){ merged += *p1; } else if(*p1 == '\0' && *p2 != '\0'){ merged += *p2; } } return merged; } };
LeetCode返回的错误信息:
================================================================= ==22==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fa4c5900390 at pc 0x559334397d01 bp 0x7ffebc3d6450 sp 0x7ffebc3d6448 READ of size 1 at 0x7fa4c5900390 thread T0 #3 0x7fa4c7591d8f (/lib/x86_64-linux-gnu/libc.so.6+0x29d8f) (BuildId: c289da5071a3399de893d2af81d6a30c62646e1e) #4 0x7fa4c7591e3f (/lib/x86_64-linux-gnu/libc.so.6+0x29e3f) (BuildId: c289da5071a3399de893d2af81d6a30c62646e1e) Address 0x7fa4c5900390 is located in stack of thread T0 at offset 144 in frame This frame has 3 object(s): [32, 33) 'ref.tmp' [48, 80) 'agg.tmp' [112, 144) 'agg.tmp8' <== Memory access at offset 144 overflows this variable HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork (longjmp and C++ exceptions *are* supported) Shadow bytes around the buggy address: 0x7fa4c5900100: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 0x7fa4c5900180: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 0x7fa4c5900200: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 0x7fa4c5900280: f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 f5 0x7fa4c5900300: f1 f1 f1 f1 01 f2 00 00 00 00 f2 f2 f2 f2 00 00 =>0x7fa4c5900380: 00 00[f3]f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 0x7fa4c5900400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7fa4c5900480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7fa4c5900500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7fa4c5900580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0x7fa4c5900600: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 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 ==22==ABORTING
错误原因
核心问题是非法访问了字符串内存范围外的区域,具体细节:
- 逻辑判断错误:代码用
*p1 != '\0'和*p2 != '\0'判断字符是否存在,这是C风格字符串的判断逻辑,但C++的std::string并不依赖末尾的'\0'管理边界,当索引i超过字符串长度时,&word1[i]或&word2[i]属于越界访问,是未定义行为。 - 测试用例触发场景:以给定测试用例为例,
word2长度为4,当循环i从4开始时,访问word2[i]已经超出了word2的有效内存范围(有效索引为0-3),此时读取该位置内存属于栈溢出,被LeetCode的AddressSanitizer(内存检测工具)捕获并抛出错误。 - 本地无报错的原因:未定义行为的结果具有随机性,本地环境中越界位置的内存可能恰好是
'\0',让代码逻辑“侥幸”运行,但这并不代表代码正确,LeetCode的严格内存检测暴露了这个问题。
内容的提问来源于stack exchange,提问作者fbk
相关产品推荐
相关产品推荐

