最长回文子串代码触发堆溢出(AddressSanitizer报错)求助
问题定位与修复
核心错误点
你的堆溢出问题根源在shift_left函数里的sizeof(c):
const unsigned short int size = sizeof(c);
这里c是char*类型的指针,sizeof(c)得到的是指针本身的大小(64位系统下是8字节,32位是4字节),而不是你用new char[s.length()]分配的数组实际长度。当输入字符串长度为5时,你只分配了5字节的堆内存,但shift_left里却按8字节来操作memmove和memset,直接导致读写超出堆内存边界,触发AddressSanitizer的溢出错误。
修复方案
需要把数组的实际长度传递给shift_left函数,而不是通过指针计算大小。同时补充内存管理和字符串终止符的细节,避免其他潜在问题:
- 修改
shift_left函数,增加数组长度参数:
void shift_left(char* c, const short unsigned int bits, const size_t arr_len) { memmove(c, c+bits, arr_len - bits); memset(c+arr_len-bits, 0, bits); }
在调用
shift_left的两处位置,传入数组实际长度s.length():- 第一处:
shift_left(output, bits, s.length());- 第二处:
shift_left(output, 1, s.length());修正数组分配逻辑,预留字符串终止符位置:
原代码用new char[s.length()]分配的数组没有存'\0'的空间,构造string temp(output)时会读取未知内存,改为:
char* output = new char[s.length() + 1]; output[0] = s[0]; output[1] = '\0'; // 初始化终止符
- 补充内存释放:原代码未释放
output的堆内存,添加delete[] output;避免泄漏。
修复后的完整代码
#include<string> #include<cstring> class Solution { void shift_left(char* c, const short unsigned int bits, const size_t arr_len) { memmove(c, c+bits, arr_len - bits); memset(c+arr_len-bits, 0, bits); } public: string longestPalindrome(string s) { if (s.empty()) return ""; char* output = new char[s.length() + 1]; output[0] = s[0]; output[1] = '\0'; string res = string(1, s[0]); char* n = output; auto e = s.begin() + 1; while(e != s.end()) { char letter = *e; char* c = n; (*++n) = letter; *(n+1) = '\0'; // 更新字符串终止符 if((letter != *c) && (c == &output[0] || letter != (*--c)) ) { ++e; continue; } bool need_shift = false; while((++e) != s.end() && c != &output[0]) { if((letter = *e) != (*--c)) { const unsigned short int bits = c - output + 1; shift_left(output, bits, s.length()); n -= bits; *(n+1) = '\0'; need_shift = true; break; } (*++n) = letter; *(n+1) = '\0'; } string temp(output); if (temp.length() > res.length()) { res = temp; } shift_left(output, 1, s.length()); --n; *(n+1) = '\0'; } delete[] output; // 释放堆内存 return res; } };
内容的提问来源于stack exchange,提问作者Mamert Vonn Santelices
相关产品推荐
相关产品推荐

