多次调用整数组合生成函数触发std::logic_error的异常排查
异常触发原因
- 带长度参数的组合生成函数存在逻辑缺陷
循环限制遍历范围为i < numItems,内部判断i >= numItems为永远不成立的无效条件;当循环走到最后一个有效索引i = numItems -1时,代码访问combo[i+1],属于超出vector边界的非法内存读取。
同时当前逻辑未处理“整个组合为从下界开始的连续序列”的边界场景:本来需要直接将最后一个元素递增,但代码错误依赖越界读取的内存值做判断,逻辑完整性缺失。 - 栈内存复用导致了偶发触发异常的现象
第一次外层循环运行时,combo向量后方紧邻的栈内存残留值随机,多数场景下非法读取到的值刚好满足combo[numItems-1] +1 != 越界值,可以正常返回。
第一次循环结束后,栈上残留了之前生成组合时留下的连续递增值序列。第二次循环新建的combo虽然逻辑上是空的,但复用了同一块栈内存区域,当combo长度增长到k时,越界读到的combo[k]位置的值刚好是上一次残留的连续值,满足combo[k-1] +1 == 越界值,导致判断条件不成立,整个循环执行完毕没有任何返回语句,最终走到抛出std::logic_error的分支。 - 冗余代码干扰排查方向
第一个重载返回false时已经主动调用combo.clear()清空内容,第二个重载里重复写的combo.clear()不属于bug成因,也没有实际功能。
修复方案
可根据需求选择最小改动修复或标准实现替换:
- 最小改动保留原有从前往后遍历的逻辑,补充边界判断移除越界访问:
for (int i = 0; i < numItems; ++i) { // 到达最后一个元素时直接处理,不再越界访问 if (i == numItems -1 || combo[i]+1 != combo[i+1]) { ++combo[i]; return true; } else { combo[i] = lowerBound + i; } } - 替换为可靠性更高的标准字典序组合生成逻辑(从后向前遍历找可递增位置):
for (int i = numItems - 1; i >= 0; --i) { if (combo[i] < upperBound - (numItems - i - 1)) { combo[i]++; for (int j = i + 1; j < numItems; ++j) { combo[j] = combo[i] + (j - i); } return true; } } combo.clear(); return false;
内容的提问来源于stack exchange,提问作者user314
相关产品推荐
相关产品推荐

