递归符号校验函数报“并非所有控制路径都有返回值”如何解决
错误根因分析
- 编译报错的直接原因:函数存在没有返回值的代码分支。外层第一个
if条件匹配后,如果内部的OrderSelect调用返回false,代码不会进入内层if代码块,也没有对应的返回语句,直接走到函数末尾,触发编译器的“不是所有控制路径都返回值”报错。 - 额外隐藏问题:
- 递归传参使用后置自增
iter++,实际传给下一层递归的是自增前的旧值,会导致递归永远遍历同一个下标,最终触发栈溢出死循环 - 边界判断
(iter + 1) != ArraySize(m_symbols)会漏掉数组最后一个元素的校验,逻辑存在漏洞 default分支重入递归时没有递增下标,如果一直命中default分支会进入死递归
- 递归传参使用后置自增
修复方案
针对以上问题做四处调整即可解决报错和隐藏风险:
- 为
OrderSelect调用失败的分支补充递归调用逻辑,继续校验下一个订单,补全返回值 - 把递归传参的后置自增
iter++改为直接传iter + 1,保证下一层递归拿到正确的遍历下标 - 修正边界判断为
iter < ArraySize(m_symbols),覆盖所有数组元素 default分支补充下标递增逻辑,避免死递归
修复后代码如下:
bool OrderManager::Check_Risk(const string symbol, uint iter = 0) { // 修正边界判断,覆盖所有数组元素 if(iter < ArraySize(m_symbols) && m_trade_restrict != LEVEL_LOW) { if(OrderSelect(OrderManager::Get(m_orders[iter]), SELECT_BY_TICKET)) { string t_base = SymbolInfoString(OrderSymbol(), SYMBOL_CURRENCY_BASE); string t_profit = SymbolInfoString(OrderSymbol(), SYMBOL_CURRENCY_PROFIT); string c_base = SymbolInfoString(symbol, SYMBOL_CURRENCY_BASE); string c_profit = SymbolInfoString(symbol, SYMBOL_CURRENCY_PROFIT); switch(m_trade_restrict) { case LEVEL_STRICT: { if(t_base == c_base || t_profit == c_profit) { return false; } else return Check_Risk(symbol, iter + 1); }; case LEVEL_NORMAL: { if(symbol == OrderSymbol()) { return false; } else return Check_Risk(symbol, iter + 1); }; default: { ENB_Trade_Restrictions(default_level); return Check_Risk(symbol, iter + 1); } } } else { // OrderSelect调用失败时继续校验下一个订单 return Check_Risk(symbol, iter + 1); } } else { return true; } }
补充说明
该校验逻辑用普通for循环遍历实现会更简洁,也可以避免递归带来的栈溢出、下标错误等问题,复杂度更低更易维护。
内容的提问来源于stack exchange,提问作者Dylan Williams
相关产品推荐
相关产品推荐

