Announcement

Collapse
No announcement yet.

Memory management of pointer created in the constructor.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Memory management of pointer created in the constructor.

    Hi!

    I'm new to Unreal Engine and I'm watching C++ Tanks vs Zombies Live Training.
    At one point a Spring Arm component is created inside the constructor.
    I would like to understand how the memory of this pointer is handled and whether memory leakage can occur in this way, since the variable is not defined as UPROPERTY ().

    Code:
    ATank::ATank()
      {
          ...
          USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
          SpringArm->AttachTo(RootComponent);
          ...
      }
    Thank you!

    #2
    There should be at least one other counted pointer in the Actor, since it needs to reference all its components. So as soon as you destroy the actor, the SpringArm should be destroyed, too. Your pointer is not of any importance because it leaves scope when you leave the constructor.

    Comment


      #3
      Variables declared inside function scope are destroyed once that function returns...
      For example if you reference SpringArm from outside ATank() constructor you're going to reach unpredictable behavior, maybe causing crashes, but not really leaking.
      | Savior | USQLite | FSM | Object Pool | Sound Occlusion | Property Transfer | Magic Nodes | MORE |

      Comment


        #4
        Thank you birdfreeyahoo and BrUnO XaVIeR!!

        Exactly as you said birdfreeyahoo, there are others counted pointers:

        Code:
        ATank::ATank()
        {
           // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
            PrimaryActorTick.bCanEverTick = true;
        
            if (!RootComponent)
            {
                RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("TankBase"));
            }
        
            SpawnCollisionHandlingMethod = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
        
            TankDirection = CreateDefaultSubobject<UArrowComponent>(TEXT("TankDirection"));
            TankDirection->AttachTo(RootComponent);
        
            TankSprite = CreateDefaultSubobject<UPaperSpriteComponent>(TEXT("TankSprite"));
            TankSprite->AttachTo(TankDirection);
        
            ChildTurret = CreateDefaultSubobject<UChildActorComponent>(TEXT("Turret"));
            ChildTurret->AttachTo(TankDirection);
        
        USpringArmComponent* SpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("SpringArm"));
            SpringArm->TargetArmLength = 500.0f;
            SpringArm->CameraLagSpeed = 2.0f;
            SpringArm->bDoCollisionTest = false;
            SpringArm->bEnableCameraLag = true;
            SpringArm->bEnableCameraRotationLag = false;
            SpringArm->bUsePawnControlRotation = false;
            SpringArm->bDoCollisionTest = false;
            SpringArm->AttachTo(RootComponent);
            SpringArm->SetWorldRotation(FRotator(-90.0f, 0.0f, 0.0f));
        
            CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera"));
            CameraComponent->bUsePawnControlRotation = false;
            CameraComponent->ProjectionMode = ECameraProjectionMode::Orthographic;
            CameraComponent->OrthoWidth = 1024.0f;
            CameraComponent->AspectRatio = 4.0f / 3.0f;
        CameraComponent->AttachTo(SpringArm, USpringArmComponent::SocketName);
            CameraComponent->SetWorldRotation(FRotator(-90.0f, -90.0f, 0.0f));
        
            MoveSpeed = 100.0f;
            MoveAccel = 200.0f;
            YawSpeed = 180.0f;
        }
        BrUnO XaVIeR for it being a pointer I thought it would be a wasted space when the class was destroyed without being able to have his memory released! Thank you for your explanation!

        Comment


          #5
          The spring arm is kept alive because the component you attached it to has a UProperty for its children, and your actor has a UProperty for the root component, so there's a valid chain of references for GC.

          If you destroy the actor, both components are destroyed together in the next GC cycle.

          This setup is somewhat inconvenient though, because you can't modify/access the spring arm in blueprint subclasses unless you create a separate UProperty for it.
          Last edited by Zeblote; 09-24-2018, 12:22 AM.

          Comment


            #6
            Tl:dr - don't do it.

            Comment


              #7
              Just to be clear, the Component object will exist as long its owner isn't GCed or it isn't deleted...
              Code:
              USpringArmComponent* SpringArm
              That pointer is what's cleaned up and destroyed as soon the Constructor() finished execution.
              From his post I understand he was asking about the pointer and not the object created;

              So it's fine to do that, there's no problem. C++ compiler deals with this stuff by itself automatically, it is very aware of what to do when a pointer is temporary within a function body.
              | Savior | USQLite | FSM | Object Pool | Sound Occlusion | Property Transfer | Magic Nodes | MORE |

              Comment


                #8
                Yeah I mean technically it works, but it should be considered an awful practice IMO so I would generally discourage it.

                I feel it's worth pointing out to OP that this only really works because all the underlying systems Unreal provides in the way of handling UObject/Actor Component lifetime etc. Putting aside what a modern compiler may or may not do for you (which you shouldn't really rely on either way) - in regular C++, this would be pretty terrible. I'm surprised this is in the official training tbh.

                But yeah - so long as there is a UPROPERTY somewhere referencing that component, then the component itself will hang around until that property or the object containing it is cleared.

                Just, please, for me.. don't do stuff like this.

                Comment

                Working...
                X