LeetCode 844题解出现AddressSanitizer负尺寸参数错误求助
先看你遇到的问题:输入S = "ab##"和T = "c#d#"时触发了AddressSanitizer的negative-size-param错误,这本质是代码里的非法内存访问,咱们一步步拆解问题出在哪:
你的代码里的核心问题
1. 越界访问字符串索引
你在循环里直接写了if(S[i+1]=='#'),当i是字符串最后一个字符时(比如S="ab##"的i=3),i+1等于S.length(),这时候访问S[i+1]属于越界访问,会破坏内存结构,触发未定义行为。
2. 处理退格符时未检查容器是否为空
当遇到#时,你直接执行a.erase(a.begin()+id-2),但如果此时vector里只有当前的#(比如第一个字符就是#,或者前面的字符已经被删完了),id-2会变成负数,比如id=1时,id-2=-1,a.begin()+(-1)是非法迭代器,这就是你看到的negative-size-param错误的直接原因。
拿S="ab##"举例:
- 当
i=3时,你push了#,id变成2; - 进入
if(S[i]=='#')分支,执行a.erase(a.begin()+2-2)也就是a.begin()+0,删掉了之前的a,id减到1; - 接着执行
a.erase(a.begin()+1-1)也就是a.begin()+0,但此时vector已经是空的了,erase空容器的迭代器直接触发内存错误。
3. 提前跳过索引的逻辑混乱
你写的if(S[i+1]=='#')分支里,直接i+=2跳过后续字符,但没有正确维护id的数值,而且这种跳过逻辑本身不符合退格的处理逻辑——连续的退格符应该逐个处理,而不是跳过,这会导致vector的状态和id完全不匹配,后续的所有操作都会出错。
4. 最后比较的逻辑有漏洞
当a和b长度不同时,你依然会循环遍历a的长度,访问b[i]会导致越界;而且一旦发现字符不相等就设置x=false,但后面的循环会覆盖这个值,比如前面不相等后面相等,x会被错误地改成true。
修复后的简洁解法
其实处理这类退格问题,用栈的思路最直接,而且不容易出错:遍历字符串,遇到非#就入栈,遇到#且栈不为空就出栈,最后比较两个栈的结果即可。
class Solution { public: bool backspaceCompare(string S, string T) { return buildProcessedString(S) == buildProcessedString(T); } private: string buildProcessedString(const string& s) { string result; for (char c : s) { if (c != '#') { result.push_back(c); } else if (!result.empty()) { // 只有栈不为空时才退格 result.pop_back(); } // 如果是#且栈为空,什么都不做 } return result; } };
这个写法避免了所有索引计算的坑,逻辑清晰,完全符合题目要求,而且能正确处理所有边界情况(比如开头就是#、连续多个#等)。
内容的提问来源于stack exchange,提问作者mecdeality

