UE4 Lua虚拟机循环调用Next引发栈溢出问题求助
UE4 Lua JSON对象合并的无限循环与栈溢出问题
开发UE4 Lua虚拟机的JSON对象系统时,JSON对象合并功能出现问题:使用while循环结合IterateTable函数遍历table时,调用Next或包含Next的函数会触发无限循环,进而引发栈溢出崩溃。
期望实现的逻辑:当Original和ToMerge拥有相同键,且该键对应的值为table时,递归合并这两个table,完成后回到原循环继续执行。
遍历用户数据对象的映射元素
void UJsonMergetFunctionLibrary::MergeLuaJsonObject(UMyDynamicObject* Origional, UMyDynamicObject* ToMerge, bool Override) { //Get all user data object keys for (TPair<FString, FLuaValue>& P: ToMerge->GetTableContent()) { //Holds the value of current key FLuaValue Hold; if (Origional->hasField(P.Key)) { if ((P.Value.Type == ELuaValueType::Table) || (P.Value.Type == ELuaValueType::UObject)) { Hold = Origional->LuaGetField(P.Key); MergeLuaJsonObject(Hold, P.Value, Override); } else if (Override) { Origional->LuaSetField(P.Key, P.Value); } } else { Origional->LuaSetField(P.Key, P.Value); } } }
遍历Lua table或用户数据对象的元素
void UJsonMergetFunctionLibrary::MergeLuaJsonObject(FLuaValue& Origional, FLuaValue& ToMerge, bool Override) { if (Origional.Type != ToMerge.Type) { if (Override) { Origional = ToMerge; return; } else { return; } } //Table if ((Origional.Type == ELuaValueType::Table) || (ToMerge.Type == ELuaValueType::Table)) { TPair<FLuaValue, FLuaValue> Pair; int32 MaxDex = MaxTableIndex(Origional); while (IterateTable(ToMerge, Pair)) { if (Pair.Key.Type == ELuaValueType::Integer) { MaxDex += 1; Origional.SetFieldByIndex(MaxDex, Pair.Value); } else if (HasTableField(Origional, Pair.Key.ToString())) { FLuaValue Hold = Origional.GetField(Pair.Key.ToString()); if ((Pair.Value.Type == ELuaValueType::Table) && (Hold.Type == ELuaValueType::Table)) { //Hold = OrigionalObj->LuaGetField(P.Key); MergeLuaJsonObject(Hold, Pair.Value, Override); } else if((Pair.Value.Type == ELuaValueType::UObject) && (Hold.Type == ELuaValueType::UObject)) { MergeLuaJsonObject(Hold, Pair.Value, Override); } else if (Override) { Origional.SetField(Pair.Key.ToString(), Pair.Value); } } else { Origional.SetField(Pair.Key.ToString(), Pair.Value); } } } //Object else if ((Origional.Type == ELuaValueType::UObject) || (ToMerge.Type == ELuaValueType::UObject)) { UMyDynamicObject* ToMergeObj = Cast<UMyDynamicObject>(ULuaBlueprintFunctionLibrary::Conv_LuaValueToObject(ToMerge)); UMyDynamicObject* OrigionalObj = Cast<UMyDynamicObject>(ULuaBlueprintFunctionLibrary::Conv_LuaValueToObject(Origional)); TMap<FString, FLuaValue> Keys = ToMergeObj->GetTableContent(); for (TPair<FString, FLuaValue>& P: Keys) { FLuaValue Hold; if (OrigionalObj->hasField(P.Key)) { if ((P.Value.Type == ELuaValueType::Table) || (P.Value.Type == ELuaValueType::UObject)) { Hold = OrigionalObj->LuaGetField(P.Key); MergeLuaJsonObject(Hold, P.Value, Override); } else if (Override) { OrigionalObj->LuaSetField(P.Key, P.Value); } } else { OrigionalObj->LuaSetField(P.Key, P.Value); } //OrigionalObj->LuaSetField(P.Key, P) } Origional = FLuaValue(OrigionalObj); } }
遍历并获取table中的下一个键
bool UJsonMergetFunctionLibrary::IterateTable(FLuaValue Table, TPair<FLuaValue, FLuaValue>& Pair) { if (Table.Type != ELuaValueType::Table) return false; ULuaState* L = Table.LuaState; if (!L) return false; if (Pair.Key.IsNil()) { L->FromLuaValue(Table); L->PushNil(); // first key } if (L->Next(-2)) { Pair.Key = L->ToLuaValue(-2); Pair.Value = L->ToLuaValue(-1); if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Yellow, Pair.Key.ToString()); L->Pop(); // pop the value return true; } else { L->Pop(); // pop the table return false; } }
检查table是否包含指定键
bool UJsonMergetFunctionLibrary::HasTableField(FLuaValue Table, FString FieldName) { if (Table.Type != ELuaValueType::Table) return false; ULuaState* L = Table.LuaState; if (!L) return false; L->FromLuaValue(Table); L->PushNil(); // first key while (L->Next(-2)) { FLuaValue Key = L->ToLuaValue(-2); if (Key.ToString() == FieldName) { L->Pop(); // pop the value L->Pop(); // pop the table return true; } else { L->Pop(); // pop the value } } L->Pop(); // pop the table return false; }
已尝试的无效方法
- 在循环内调用Next时弹出值和键,结束内部Next调用后重新赋值旧键;
- 搜索相关解决方案但无结果;
- 为循环执行次数添加限制,测试是否由无限循环导致崩溃;
- 编写纯Lua函数遍历table并调用Next(未成功,本人Lua经验尚浅)。
内容的提问来源于stack exchange,提问作者The Darkest Edge Lord
相关产品推荐
相关产品推荐

