Download

Use new[] allocates memory to a pointer member in UObject class not need to delete it explicitly?

Hello,
I have a class derived from UObject class, there is a pointer member in my class, I use new ] operator allocates memory to the pointer member when the class constructed.When I use delete] operator to free the memory explicitly when the class deconstructed, it will trigger a error in FMemory::Free function when I quit game(stop play), UE4 editor crashed. But I do nothing when the class deconstructed, there is no error when I quit game.

So use new] operator allocates memory to a pointer member in UObject class not need to delete it Explicitly?

Thanks

I’m pretty sure you’d have to handle any dynamic memory allocation that’s done outside of GC. Why not use smart pointers to handle those allocations?

Are you calling ‘new’ inside the vanilla uobject or does it happen to be inside an Actor?

Is this thing you are manually calling new on, a unreal managed type (i.e. is there any macros like UCLASS) or something completely external to UE4’s managed types?

If it’s not a UE4 managed type, you definitely will need to manage the memory yourself (i.e. if you new, you need to delete) though I’d recommend looking at C++ smart pointers (shared_ptr and unique_ptr). I believe UE4 also has a smart pointer system you can use for some non UE stuff too.

The fact that you mention FMemory::Free, makes me think you are trying to ‘new’ a UE4 managed type, in which case you likely want to not be doing what you are doing. But without more information/example, it’s hard to point out whats wrong.

If you just want to new up another UE4 UObject, look at NewObject<>()

But I have did a test, I added break points in new] and delete], and step into it, the new] operator call FMemory::Malloc and delete] call FMemory::Free, seems UE4 overload new and delete operator?

Yes, it’s UCLASS,
Here is my class


//.h file

UCLASS(BlueprintType, Blueprintable)
class IPCAMERA_API UIPCamera : public UObject
{
    GENERATED_BODY()
public:  

    BYTE* m_picBuffer = NULL;//BYTE =(unsigned char)

UFUNCTION(BlueprintPure, meta = (DisplayName = "Construct IPCamera"))
    static UIPCamera* ConstructIPCamera();

    ~UIPCamera();
};

//.CPP file

UIPCamera* UIPCamera::ConstructIPCamera()
{

    UIPCamera* pIPCamera = NewObject<UIPCamera>();


    pIPCamera->m_picBuffer = new BYTE[4096]{ 0 };

    return pIPCamera;
}

UIPCamera::~UIPCamera()
{    
    if (m_picBuffer)
    {
        //delete] m_picBuffer;// manually delete will cause a error in FMemory::Free function.
    }  
}

Ah interesting. Thats strange that doesn’t work. It looks like it should.

Let me try a few things out and see if I find anything.

I was able to run this from inside my UObject’s Constructor successfully.



// .h file
UCLASS(BlueprintType)
class TASGAME_API UMainContainerBase : public UObject
{
    GENERATED_BODY()
public:
    UMainContainerBase();
    ~UMainContainerBase();
    BYTE* someArray = nullptr;
....


// .cpp file

UMainContainerBase::UMainContainerBase()
{
    UE_LOG(LogTemp, Warning, TEXT("%p ctor start"), this);
    UE_LOG(LogTemp, Warning, TEXT("%p Am I the CDO?: %d"), this, HasAnyFlags(EObjectFlags::RF_ClassDefaultObject));
    {
        someArray = new BYTE[100]{0};
        someArray[0] = 3;
        UE_LOG(LogTemp, Warning, TEXT("%p someArray[0]=%d"), this, someArray[0]);
    }
    UE_LOG(LogTemp, Warning, TEXT("%p ctor End"), this);
}

UMainContainerBase::~UMainContainerBase()
{
    UE_LOG(LogTemp, Warning, TEXT("%p Am I the CDO?: %d"), this, HasAnyFlags(EObjectFlags::RF_ClassDefaultObject));
    if (someArray)
    {
        UE_LOG(LogTemp, Warning, TEXT("%p dtor someArray[0]=%d"), this, someArray[0]);
        delete someArray;
        someArray = nullptr;
    }
    else
    {
        UE_LOG(LogTemp, Warning, TEXT("%p dtor someArray is null?"), this);
    }
}


Here are my logs




// Started compiling
Warning: Starting HotReload took  0.0s.
...
LogTemp: Warning: 000001CEB92E3470 ctor start
LogTemp: Warning: 000001CEB92E3470 Am I the CDO? 1
LogTemp: Warning: 000001CEB92E3470 someArray[0]=3
LogTemp: Warning: 000001CEB92E3470 ctor End
...
LogTemp: Warning: 000001CEB92E0590 Am I the CDO? 1
LogTemp: Warning: 000001CEB92E0590 dtor someArray is null?
LogTemp: Warning: 000001CEC3FC65C0 Am I the CDO? 1
LogTemp: Warning: 000001CEC3FC65C0 dtor someArray[0]=3
...
// Finished compiling
Display: HotReload took  2.7s.
// I hit play
LogTemp: Warning: 000001CED7757BF0 ctor start
LogTemp: Warning: 000001CED7757BF0 Am I the CDO? 0
LogTemp: Warning: 000001CED7757BF0 someArray[0]=3
LogTemp: Warning: 000001CED7757BF0 ctor End
...
LogTemp: Warning: 000001CED7755120 ctor start
LogTemp: Warning: 000001CED7755120 Am I the CDO? 0
LogTemp: Warning: 000001CED7755120 someArray[0]=3
LogTemp: Warning: 000001CED7755120 ctor End
...
// I exited my game
LogTemp: Warning: 000001CED7755120 Am I the CDO? 0
LogTemp: Warning: 000001CED7755120 dtor someArray[0]=3
LogTemp: Warning: 000001CED7757BF0 Am I the CDO? 0
LogTemp: Warning: 000001CED7757BF0 dtor someArray[0]=3
...



Note: that I have some DTORs with addresses that there with no equivalent CTORs for, they are from my previous ‘compile’ when the earlier CDOs were made. For example, if I recompile my project, I see the dtor for 000001CEB92E3470.
Note: I tried using NULL and nullptr (no difference for me as expected)
Note: I tried using delete and delete] (no difference for me)

In my above example, I experienced no crashes or issues.

How familiar are you with the concept of CDO (Class Default Object) and UE4 UCLASS lifetime of an object?

@namrog84,
I have no ideal of CDO.
Btw, I have created a FNonAbandonableTask thread to referenced the UIPCamera instanced object. Maybe because of this?

You should do some reading about CDOs as UE4’s lifecycle of objects are a bit funky. Especially since you have that static helper constructor and might need to do some more complex things. I know how they work for Actors, but I am not sure if they behave the same way for UObjects.

If you are doing something multi threaded.

  • Could you be double freeing? (After you call delete, set your array back to NULL or nullptr so that you don’t call delete on it again. Calling delete doesn’t set it to 0 (NULL/nullptr), so your if(cond) might not be working as you think it is.
  • You might need some mutex locks in certain places. I am not sure how you are holding onto the reference across threads, but maybe something in this area?

I’d suggest doing some additional UE_LOGs as I’ve done with the %p for pointers to which memory you are trying to access. Or add a bunch of debug breaks (whichever is your style). I will use debug breaks on more specific things that I am trying to understand, but in this case I just wanted to see lifetime of when ctor and dtors were being called on which objects.

And then try to better grasp the full picture of whats going on. I am not at all familiar with FNonABandonableTask and how they work so exploring that is out of scope for me. :frowning: I’ve shared what help I can, and my situation works for me. So there must be something else going on here in your code.