28.3.3.2. Flight Task 객체의 소멸자(Destructor) 처리 및 리소스 반환 안전성 검증
앞서 살펴본 Placement new를 통한 객체 덮어쓰기(Overwrite) 기법은 매우 빠르고 효율적이지만, 치명적인 잠재적 위험을 내포하고 있다. 새로 입주하는 객체가 짐을 풀기 전에 방을 빼는 이전 객체가 자신이 쓰던 쓰레기(리소스)를 완벽하게 치우고 나가지 않으면 시스템 전체가 붕괴된다는 점이다.
따라서 FlightModeManager는 _current_task->~FlightTask(); 라인을 통해 이전 모드의 명시적 소멸자(Explicit Destructor)를 반드시 호출하며, 이 소멸자 내부에서는 가혹하리만치 철저한 리소스 반환 검증 수학이 동작한다.
1. 파일 디스크립터(File Descriptor) 누수 방지: uORB 구독 해제
NuttX RTOS 환경에서 구현된 FlightTask 클래스들은 각자의 비행 로직을 수행하기 위해 다양한 uORB 토픽을 구독(Subscribe)한다. 예를 들어 FlightTaskAutoMapper는 미션 아이템을 받기 위해 position_setpoint_triplet 토픽을 열어둔다.
OS 레벨에서 uORB 토픽을 구독한다는 것은 한정된 자원인 파일 디스크립터(fd)를 하나 잡아먹는다는 뜻이다.
- 구독 해제(Unsubscribe) 누락의 참변: 만약 소멸자에서 이 토픽 구독을 해지(
orb_unsubscribe())하지 않고 그냥 새 비행 모드로 덮어써 버리면 어떻게 될까? 조종사가 모드를 전환할 때마다 파일 디스크립터가 하나씩 영구적으로 유실(Leak)된다. 결국 수십 번의 모드 전환 끝에 OS의 최대 fd 한도에 도달하게 되고, 센서 데이터를 읽어오는 핵심 스레드마저 토픽을 열지 못해 드론이 공중에서 먹통이 되어 추락하게 된다. - Virtual 소멸자 체인: 따라서
FlightTask기저 클래스의 소멸자virtual ~FlightTask();를 필두로, 모든 자식 클래스들은 각자가 파생 과정에서 뚫어놓은 고유의 uORB 구독 핸들(Handle)들을 소멸자 스코프 내에서 완벽하게 닫아주는 코드를 필수적으로 구현해야 한다.
2. 잔여 상태(Dangling State)의 초기화 보장
Placement new 연산자는 운영체제가 제공하는 깨끗하게 포맷된 0(Null)으로 채워진 메모리를 주는 것이 아니다. 이전 객체가 방금 전까지 쓰던 수만 가지의 쓰레기 변수 데이터 잔해(Garbage Data)가 그대로 남아있는 물리적 RAM 주소 공간을 그대로 물려받을 뿐이다.
- 소멸자는 메모리 공간 자체를 파괴할 수는 없지만(어차피 정적 할당된 배열이므로), 최소한 자신이 동적으로 연결해 두었던 외부 포인터(Pointer) 연결망이나 콜백(Callback) 레퍼런스들을 안전하게
nullptr로 끊어주는 역할을 수행한다. - 이는 다음에 이 공간에 새로 입주할
FlightTask인스턴스의 생성자(Constructor)가 예측 불가능한 이전 객체의 쓰레기 메모리 값에 오염되어 잘못된 초기화를 진행하는 것을 막아주는 최소한의 방화벽 역할을 한다.
결론적으로, PX4의 FMM 아키텍처에서 FlightTask의 소멸자는 메모리 공간 자체의 회수(Free) 목적이 아니라, 운영체제(OS)의 커널 리소스(uORB 핸들 등)를 반환하고 논리적인 상태 찌꺼기를 세탁하기 위한 **필수 불가결한 리소스 청소부(Resource Janitor)**로서 설계되었음을 의미한다.