SetPropertyValue() corrupts object?!

Problem:

If I create an object and set a property using the reflection system the object becomes invalid - it fails an assert in ConditionalDestroy() - it is caused because when the BeginDestroy() function is called on the object somehow the PostLoadSubobjects() is called instead, and BeginDestory() isn’t called at all.

Code I used:

UCLASS(BlueprintType, EditInlineNew)
class TPSTEST_API UTestObjectBase : public UObject
{
	GENERATED_BODY()
	
protected:

	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Params)
	bool bTestParam = true;
};

In character Header:

UPROPERTY()
class UTestObjectBase* ObjectPtr;

Character BeginPlay:

//////////////////////////////////////////////////////////////////////////
void ATPSTestCharacter::BeginPlay()
{
	ObjectPtr = NewObject<UTestObjectBase>(this, UTestObjectBase::StaticClass());

	UBoolProperty* Property = Cast<UBoolProperty>(ObjectPtr->GetClass()->FindPropertyByName("bTestParam"));
	if (Property != nullptr)
		Property->SetPropertyValue(reinterpret_cast<void*>(ObjectPtr), false);
}

Easiest way to reproduce:

  1. Create a C++ tps template project (4.15)
  2. Paste the attached files (overwriting the default character .h/.cpp).
  3. Start the game in editor
  4. Press esc to stop it

Interesting part is the fact that the error looks totally random, but I had exactly the same results in a much more complicated environment.
Did I miss something?

Edit: I guess I misunderstood how SetPropertyValue() works, and it expects a pointer to bTestParam and not a pointer to the object containing it?
I still did not find the right way to do this, but I’ll keep looking…

Using SetPropertyValue_InContainer() instead of SetPropertyValue() solved the problem.

1 Like

Yes, I found the problem too.
_InContainer expects an Object pointer (ObjectPtr in this case), but the simple version expects a pointer to the variable itself (bTestParam in this case).

It isn’t really clear, but whatever, at least I figured it out :stuck_out_tongue:

I think issue might be cast, void* should accept any pointer type (including function pointers) as it’s ambiguous type just containing memory address and it can take it from any other pointer without casting (in other word void* is a “base class” for any pointer for compiler). you might also try using _InContainer version with index 0 i remeber i had similar isues with nomal function yet the container one worked ok.