언리얼 엔진을 사용하여 학습하던 중, nullptr 또는 캐스팅된 클래스가 개발자가 의도한 클래스인지 확인하기위해 

객체 또는 유효성 검사를 하였습니다.

유효성 검사중 Succeeded, Assert, IsValid, ==nullptr 등 다양한 함수를 사용하게 되었으며,

각각 어떠한 상황에 써야지 알맞는지 학습해보았습니다.

이번 포스팅에서는 상황에 맞는 유효성 검사를 수행하는 방법에 대해 알아보겠습니다. 

 

유효성 검사

  • 객체, 클래스, 상태 등이 올바르고 기대된 조건을 충족하는지 확인하는 방법
  • 입력 데이터, 객체 상태, 연산 결과 등이 유효한지 검증한다.
  • 디버깅, 런타임등의 다양한 환경에서 프로그램의 예기치 않은 동작 혹은 오류를 방지 할 수 있다.
  • 오류 발생 위치를 명확하게 알 수 있으므로, 디버깅 과정에서 시간을 절약 할 수 있다.
  • 코드의 신뢰성 및 유지보수성을 향상시킨다.
  • 객체가 삭제되거나, 메모리에서 해제된 상태에서도 참조하는 경우(Dangling Pointer)문제 방지 가능

 

== nullptr

  • 단순히 포인터가 nullptr인지 확인한다.
  • UE엔진의 Class, Actor, Object들은 모두 포인터 방식.
    • 객체 유효성 검사시 가장 쉬운 방법
  • GC객체를 감지하지 못해 IsValid보다는 안전하지 않다
  • GC가 필요하지 않은 경우에는 적합하다.
    • 삭제된 경우, !Actor은 유효할 수 있다고 판단 할 수 있다.
    • 일반 자료형(int32*, float*), 스마트포인터, UClass 리플렉션이 없는 클래스 등

 

IsValid

  • 동적으로 생성된 객체의 유효성 검사에 특화된 함수
  • UObject를 상속한 객체의 포인터에 대한 유효성 검사
  • GC에 의해 삭제되었는지 확인 가능
  • nullptr 과 GC를 IsValid를 사용하여 확인 할 수 있다.
  • nullptr만 확인하기에는 오버헤드가 발생할 우려가 있다.
    • 단순한 nullptr 체크는 == nullptr를 사용하는것이 더 효율적이다.
  • AActor, UActorComponent 객체가 동적으로 생성된 경우 상태를 확인하기 위해 사용한다.
    • 파괴된 액터에 접근하여 크래시를 방지한다.
    • 삭제 중(IsPendingKill()인 경우, IsValid를 사용하여 삭제를 취소 할 수있다.

 

IsPendingKill

  • GC에 의해 삭제 예정 상태, 삭제 중인지 확인하고 싶을 경우 사용한다.
  • 객체가 삭제 중이지만 메모리가 여전히 존재한 경우에 사용한다.
  • nullptr의 상황은 확인하지 않는다.
  • 삭제중인 액터에 접근시, 크래시 발생 우려가 있으므로 IsPendingKill를 사용하여 확인한다.
  • 타이머/델리게이트에서 삭제된 객체를 확인한다.

 

Check

  • UE에서 디버깅중 유효성 검사를 위해 사용한다.
  • 코드에서 특성 조건이 항상 참이어야 하는 경우에 사용한다.
  • 조건이 실패시에 에디터 크래시, Assert를 출력한다.
  • 디버거에서 해당 지점을 중단점으로 잡아 잘못된 코드경로를 빠르게 확인 할  수 있다.
  • 논리적으로 실행이 안되는 코드가 실행되었을 때 크래시를 발생시키는 경우
  • Shipping 빌드시에는 사용하지 않는다.
    • Shipping 빌드시에 런타임 유효성 검사는 Ensure가 더 적합하다.
  • 개발자의 실수로 인한 경우에도 크래시를 유발 할 수 있으므로, Ensure 또는 if문을 사용한 검사가 더 효율적일 수 있다.

Ensure

  • Check와 비슷하지만, 크래시가 아닌 경고만 출력한다.
  • 조건 실패시에도 계속 실행 될 수 있다.
  • 사용자 입력의 경우 실수 가능성이 있어 Ensure를 사용하여 조건이 실패해도 계속 실행해야 하는 경우 사용한다.

Succeeded

  • 함수 실행 결과가 성공했는지에 대해 확인한다.
  • FOptionalResult, FHitResult, ConstructorHelpers같은 함수 호출 결과를 검사하는 경우 사용한다.

 

Assert

  • 조건이 실패하면 디버거 브레이크 포인트를 트리거한다.
  • Shipping 빌드시 비활성화 된다.

 

Verify

  • Shipping 빌드에서도 조건 검사를 수행한다.
  • 디버깅 및 릴리즈 환경 모두에서 조건 검증이 필요한 경우에 적합하다.
  • 실패시에 Check와 같은 크래시가 발생한다.
    • Shipping빌드 환경에서는 크래시 대신 무시된다.
    • 실패해도 크래시 대신 검증 로그를 남기고 실행을 계속해야 할 때 사용한다.
  • 특정 조건이 항상 참이여야 하는 경우에 사용하여, 런타임 환경에서도 코드 안정성을 보장한다.

 

IsTemplate

  • 객체가 CDO인지 확인하고 싶을 때
  • 클래스의 기본 값을 설정하거나, 특정 작업을 CDO에만 적용해야 하는 경우에 사용한다.
  • 게임 플레이 도중 특정 로직이 CDO에서 실행하지 않도록 제한한다.

 

GEngine→AddOnScreenDebugMessage

  • 디버깅시 메시지를 출력하고 싶을 경우 사용한다.
  • 디버깅 중 상태를 확인하기 쉽다.
  • 런타임 디버깅용으로만 사용된다.

 

 

객체 클래스 검사 및 캐스팅시의 차이점  (IsA VS Cast<T>())

 

bool UObject::IsA(const UClass* Class) const;

  • UClass타입을 확인하고자 할 때 사용한다.
  • 객체가 해당 클래스이거나, 그 클래스에서 파생된 클래스인 경우 true 반환
  • 객체 타입을 확인할 때 사용한다.
  • 런타임시 타입 정보를 확인 할 수 있다.
  • 실제 클래스 타입을 확인할 때 사용한다.

 

Cast<T>(Obj)

  • 객체를 지정된 클래스 타입으로 캐스팅 한다.
  • 타입으로 캐스팅 된 객체 포인터를 반환한다.
  • 캐스팅이 실패한 경우 nullptr를 반환한다.
  • 객체를 특정 타입으로 변환하여 작업을 수행하고자 할 때 사용한다.

 

 

 

정리

  • 디버깅 : Check, Ensure, Assert
  • 런타임 조건 검증 및 경고 : Ensure, EnsureMsgf, EnsureAlways
  • UObject 포인터 유효성 확인 : IsValid, IsPendingKill, IsValidLowLevel
  • Shipping 빌드 : Verify, Succeeded
  • 디버깅 메시지 출력 : GEngine→AddOnScreenDebugMessage

'Unreal Engine > Debugging' 카테고리의 다른 글

[UE5] UObject 클래스 내 GetWorld Null 반환  (0) 2025.02.26

+ Recent posts