为什么当某些变量传递到 `It()` lambda 时 UE4 规范会崩溃?

问题描述 投票:0回答:1

在编写 UE4 规范时,我发现有时传入 lambda 的值会导致崩溃或不可预测的结果,而其他时候却不会。

例如,在下面的示例中调用

Matcher
内的
It()
对象上的任何方法都会导致崩溃(当我在 Rider 调试器中检查它们时,所有值都是垃圾数据):

void FPF2AbilityBoostRuleOptionMatcherSpec::Define()
{
    Describe(TEXT("when there are no rule options"), [=, this]()
    {
        const TArray<FPF2AbilityBoostRuleOption> RuleOptions = {};

        Describe(TEXT("CanApplyAbilityBoost()"), [=, this]()
        {
            FPF2AbilityBoostRuleOptionMatcher Matcher(RuleOptions);

            It(TEXT("returns `false` for all abilities"), [=, this, &Matcher]()
            {
                for (const auto& AbilityScoreType : TEnumRange<EPF2CharacterAbilityScoreType>())
                {
                    TestFalse(
                        FString::Format(TEXT("CanApplyAbilityBoost({0})"), { PF2EnumUtils::ToString(AbilityScoreType)}),
                        Matcher.CanApplyAbilityBoost(AbilityScoreType)
                    );
                }
            });
        });
        // ...
    });
    // ...
}

将其切换为按值传递会导致 IDE 错误,但它的编译和崩溃与我使用引用时的情况相同:

void FPF2AbilityBoostRuleOptionMatcherSpec::Define()
{
    Describe(TEXT("when there are no rule options"), [=, this]()
    {
        const TArray<FPF2AbilityBoostRuleOption> RuleOptions = {};

        Describe(TEXT("CanApplyAbilityBoost()"), [=, this]()
        {
            FPF2AbilityBoostRuleOptionMatcher Matcher(RuleOptions);

            It(TEXT("returns `false` for all abilities"), [=, this, Matcher]()
            {
                for (const auto& AbilityScoreType : TEnumRange<EPF2CharacterAbilityScoreType>())
                {
                    TestFalse(
                        FString::Format(TEXT("CanApplyAbilityBoost({0})"), { PF2EnumUtils::ToString(AbilityScoreType)}),
                        // Next line gets highlighted in red in Rider but compiles. Error is:
                        // Cannot convert 'this' argument from type 'FPF2AbilityBoostRuleOptionMatcher const' to type
                        // 'FPF2AbilityBoostRuleOptionMatcher': function is missing 'const' qualifier`
                        Matcher.CanApplyAbilityBoost(AbilityScoreType)
                    );
                }
            });
        });
        // ...
    });
    // ...
}

尽管如此(但是必须在每个测试用例中构建

Matcher
):

void FPF2AbilityBoostRuleOptionMatcherSpec::Define()
{
    Describe(TEXT("when there are no rule options"), [=, this]()
    {
        const TArray<FPF2AbilityBoostRuleOption> RuleOptions = {};

        Describe(TEXT("CanApplyAbilityBoost()"), [=, this]()
        {
            It(TEXT("returns `false` for all abilities"), [=, this]()
            {
                FPF2AbilityBoostRuleOptionMatcher Matcher(RuleOptions);

                for (const auto& AbilityScoreType : TEnumRange<EPF2CharacterAbilityScoreType>())
                {
                    TestFalse(
                        FString::Format(TEXT("CanApplyAbilityBoost({0})"), { PF2EnumUtils::ToString(AbilityScoreType)}),
                        Matcher.CanApplyAbilityBoost(AbilityScoreType)
                    );
                }
            });
            });
        });
        // ...
    });
    // ...
}

为什么?在引用该对象之前,是否会因某种原因调用该对象的析构函数?

c++ unreal-engine4
1个回答
0
投票

正如我怀疑的那样,外部作用域中的变量正在分配堆栈,然后当它们被使用时,它们指向垃圾内存。为了避免崩溃,必须声明变量

static
,这确保在整个运行时为这些值保留内存。

© www.soinside.com 2019 - 2024. All rights reserved.