大数据集下返回含vector<uint8_t>的std::optional出现未知错误排查
问题原因
1. 测试数据构造逻辑存在内存爆炸
你main函数中循环120次执行a.insert(a.end(),a.begin(),a.end()),相当于数组大小每次翻倍,初始11个元素,循环7次就会达到1408个元素,循环120次后的理论大小是11 * 2^120,远远超出任何设备的内存上限,程序运行到中途就会因为内存不足被系统强制终止。
2. 代码缺失边界检查,存在多处未定义行为
- 第一个
while (*message.cbegin() != startSign)循环未判断vector是否为空,若vector中不存在目标起始标志,会一直erase到vector为空,此时解引用空迭代器属于越界访问,直接触发未定义行为。 - 第二个
while (*(message.cend() - 2) != endSign)循环未判断vector长度是否≥2,若vector长度不足2时执行cend()-2属于越界访问,触发未定义行为。 - 未判断
test返回的std::optional是否有值就直接用*b解引用,若前面逻辑出错导致optional为空,解引用空optional也是未定义行为,会直接崩溃。
3. 元素删除逻辑效率极低,大数据量下必然卡顿
vector的erase(begin())操作时间复杂度为O(n),每次删除头部元素都要移动后面所有元素,若需要删除的元素较多,整体时间复杂度会达到O(n²),数据量越大卡顿越明显。
修复方案
1. 修改测试数据构造逻辑
不要用翻倍的方式构造测试数据,直接按需求构造指定大小的数组即可:
int main() { std::vector<uint8_t> base = {0x01,0x01,0x01,0x01,0x01, 0x02, 0x3, 0x25, 0x65, 0x03, 0x02}; std::vector<uint8_t> a; // 构造300大小的测试数组 while(a.size() < 300) { a.insert(a.end(), base.begin(), base.end()); } auto b = test(a); if (!b.has_value()) { std::cout << "无有效数据" << std::endl; return 1; } auto c = *b; std::cout<<"size = "<<c.size()<<std::endl; return 0; }
2. 补充边界检查,优化删除逻辑
用标准库查找函数替代逐个删除,既安全且效率更高:
#include <algorithm> // 包含std::find std::vector<uint8_t> getMessageFromStartSignToEndSign(std::vector<uint8_t> message, uint8_t startSign, uint8_t endSign, bool areStartAndStopSignsLeftInResultStream) { // 查找起始标志,一次O(n)操作 auto startIt = std::find(message.cbegin(), message.cend(), startSign); if (startIt == message.cend()) { return {}; } message.erase(message.cbegin(), startIt); // 查找结束标志(从倒数第二个位置往前找) if (message.size() < 2) { return {}; } auto endRit = std::find(message.crbegin() + 1, message.crend(), endSign); if (endRit == message.crend()) { return {}; } message.erase(endRit.base(), message.cend()); if (!areStartAndStopSignsLeftInResultStream) { if (message.size() >= 2) { message.erase(message.begin()); message.pop_back(); } else { return {}; } } return message; }
内容的提问来源于stack exchange,提问作者Gameriker
相关产品推荐
相关产品推荐

