Study/에러 정리

람다식 캡쳐와 const, 공유포인터 업데이트 문제

Juzdalua 2024. 9. 8. 01:58

작업중인 스레드 내부에서 다른 스레드에게 비동기 작업을 요청하는 과정에서 문제가 발생했다.

 

정확히는 공유포인터를 매개변수로 람다식 내부에서 사용할 때 문제가 발생했다.

처음에는 참조캡쳐(&)로 메모리를 아껴야겠다는 생각을 했다.

 

주소값을 건네 받고 스레드가 작업을 시작하면 미리 선언된 공유포인터의 메모리는 해제되고 공유포인터의 주소값은 null값을 가르키게 되었다.

// Room.h
void UpdateRoomItem(shared_ptr<RoomItem>& roomItem);

// Room.cpp
void Room::UpdateRoomItem(shared_ptr<RoomItem>& roomItem)
{
	업데이트 로직
}

 

shared_ptr<RoomItem> roomItem = ItemController::GetRoomItemByRoomItemId(recvItem.roomitemid());

thread([&]() {
    this_thread::sleep_for(3s);

    ...
    GRoom.UpdateRoomItem(roomItem); // Error
    ...


    GRoom.Broadcast(MakeSendBuffer(createRoomPkt, createRoomPacketId));
    }).detach();

 

그래서 소유권을 아예 넘기면 되지 않을까 시도해봤지만 동일한 에러가 발생했다.

shared_ptr<RoomItem> roomItem = ItemController::GetRoomItemByRoomItemId(recvItem.roomitemid());

thread([&, std::move(roomItem)]() {
    this_thread::sleep_for(3s);

    ...
    GRoom.UpdateRoomItem(roomItem); // Error
    ...


    GRoom.Broadcast(MakeSendBuffer(createRoomPkt, createRoomPacketId));
    }).detach();

수정된 코드

공유포인터를 복사하면 useCount가 증가하여 레퍼런스참조가 되는 것을 미처 생각하지 못했다.

그리고 실질적으로 업데이트 되지 않는 공유포인터는 const 상수 매개변수로 넘겨주었다.

// Room.h
void UpdateRoomItem(const shared_ptr<RoomItem>& roomItem);

// Room.cpp
void Room::UpdateRoomItem(const shared_ptr<RoomItem>& roomItem)
{
	업데이트 로직
}
shared_ptr<RoomItem> roomItem = ItemController::GetRoomItemByRoomItemId(recvItem.roomitemid());

thread([=]() {
    this_thread::sleep_for(3s);

    ...
    GRoom.UpdateRoomItem(roomItem); // Error
    ...


    GRoom.Broadcast(MakeSendBuffer(createRoomPkt, createRoomPacketId));
    }).detach();

 

const를 사용할 수 있으면 모든 곳에 사용하라는 어떤 유튜버의 조언이 떠올랐다.