虚幻4OBJECT内存分配和初始化

    xiaoxiao2023-03-24  8

    首先,蓝图调用实在CPP调用之后执行。

    模块加载时候回调用所有的UClass的CreateDefaultObject函数,产生默认的OBJECT,以后拷贝默认的就行了

    在任何一个Actor构造函数里面打断点,然后play

    UnrealEngine\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp

    UObject* StaticConstructObject_Internal ( UClass* InClass, UObject* InOuter /*=GetTransientPackage()*/, FName InName /*=NAME_None*/, EObjectFlags InFlags /*=0*/, EInternalObjectFlags InternalSetFlags /*=0*/, UObject* InTemplate /*=NULL*/, bool bCopyTransientsFromClassDefaults /*=false*/, FObjectInstancingGraph* InInstanceGraph /*=NULL*/ ) { SCOPE_CYCLE_COUNTER(STAT_ConstructObject); UObject* Result = NULL; #if WITH_EDITORONLY_DATA UE_CLOG(GIsSavingPackage && InOuter != GetTransientPackage(), LogUObjectGlobals, Fatal, TEXT("Illegal call to StaticConstructObject() while serializing object data! (Object will not be saved!)")); #endif checkf(!InTemplate || InTemplate->IsA(InClass) || (InFlags & RF_ClassDefaultObject), TEXT("StaticConstructObject %s is not an instance of class %s and it is not a CDO."), *GetFullNameSafe(InTemplate), *GetFullNameSafe(InClass)); // template must be an instance of the class we are creating, except CDOs // Subobjects are always created in the constructor, no need to re-create them unless their archetype != CDO or they're blueprint generated. // If the existing subobject is to be re-used it can't have BeginDestroy called on it so we need to pass this information to StaticAllocateObject. const bool bIsNativeClass = InClass->HasAnyClassFlags(CLASS_Native | CLASS_Intrinsic); const bool bIsNativeFromCDO = bIsNativeClass && ( !InTemplate || (InName != NAME_None && InTemplate == UObject::GetArchetypeFromRequiredInfo(InClass, InOuter, InName, InFlags)) ); #if WITH_HOT_RELOAD // Do not recycle subobjects when performing hot-reload as they may contain old property values. const bool bCanRecycleSubobjects = bIsNativeFromCDO && !GIsHotReload; #else const bool bCanRecycleSubobjects = bIsNativeFromCDO; #endif bool bRecycledSubobject = false; Result = StaticAllocateObject(InClass, InOuter, InName, InFlags, InternalSetFlags, bCanRecycleSubobjects, &bRecycledSubobject); check(Result != NULL); // Don't call the constructor on recycled subobjects, they haven't been destroyed. if (!bRecycledSubobject) { FScopeCycleCounterUObject ConstructorScope(InClass, GET_STATID(STAT_ConstructObject)); (*InClass->ClassConstructor)( FObjectInitializer(Result, InTemplate, bCopyTransientsFromClassDefaults, true, InInstanceGraph) ); } if( GIsEditor && GUndo && (InFlags & RF_Transactional) && !(InFlags & RF_NeedLoad) && !InClass->IsChildOf(UField::StaticClass()) ) { // Set RF_PendingKill and update the undo buffer so an undo operation will set RF_PendingKill on the newly constructed object. Result->MarkPendingKill(); SaveToTransactionBuffer(Result, false); Result->ClearPendingKill(); } return Result; }

    Result = StaticAllocateObject(InClass, InOuter, InName, InFlags, InternalSetFlags, bCanRecycleSubobjects, &bRecycledSubobject);

    上面这一行分配内存

    (*InClass->ClassConstructor)( FObjectInitializer(Result, InTemplate, bCopyTransientsFromClassDefaults, true, InInstanceGraph) );

    上面这一行调用构造函数,我猜应该是先把上面构造那个默认的给拷贝过来,然后再调用下面的初始化函数。

    参数类型为FObjectInitializer的构造函数是在自动生成的generate.h文件中声明的,类似于这样,我的这个类名是AGame1Character

    #define Game1_Source_Game1_Game1Character_h_9_STANDARD_CONSTRUCTORS \ /** Standard constructor, called after all reflected properties have been initialized */ \ NO_API AGame1Character(const FObjectInitializer& ObjectInitializer); \ DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(AGame1Character) \ DECLARE_VTABLE_PTR_HELPER_CTOR(NO_API, AGame1Character); \ DEFINE_VTABLE_PTR_HELPER_CTOR_CALLER(AGame1Character); \

    DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL这个宏是这样

    #define DEFINE_DEFAULT_OBJECT_INITIALIZER_CONSTRUCTOR_CALL(TClass) \ static void __DefaultConstructor(const FObjectInitializer& X) { new((EInternal*)X.GetObj())TClass(X);

    enum EInternal {EC_InternalUseOnlyConstructor};

    placement new 直接在返回的object指针位置调用了构造函数。然后就调到我们写的构造函数,(上面那个还有个无参数版本,类似于  TClass())

    引擎一开始先开辟一个数组,存放所有的活着的UOBJECT。其实就是个Object的指针和这个object的flag。

    maloc其实就是单纯的开辟内存,目前没有发现内存池在哪里。在我的PC上是英特尔的TBB算法(TBB(intel threading building blocks)内存分配算法)。

    Engine_Updating\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectArray.cpp

    void FUObjectArray::AllocateObjectPool(int32 InMaxUObjects, int32 InMaxObjectsNotConsideredByGC) { check(IsInGameThread()); MaxObjectsNotConsideredByGC = InMaxObjectsNotConsideredByGC; // GObjFirstGCIndex is the index at which the garbage collector will start for the mark phase. // If disregard for GC is enabled this will be set to an invalid value so that later we // know if disregard for GC pool has already been closed (at least once) ObjFirstGCIndex = DisregardForGCEnabled() ? -1 : 0; // Pre-size array. check(ObjObjects.Num() == 0); UE_CLOG(InMaxUObjects <= 0, LogUObjectArray, Fatal, TEXT("Max UObject count is invalid. It must be a number that is greater than 0.")); ObjObjects.PreAllocate(InMaxUObjects); if (MaxObjectsNotConsideredByGC > 0) { ObjObjects.AddRange(MaxObjectsNotConsideredByGC); } }

    转载请注明原文地址: https://ju.6miu.com/read-1202285.html
    最新回复(0)