[.NET] A callback was made on a garbage collected delegate of type 기술 이야기 2020. 6. 11. 23:13

잘 동작하던 API가 갑자기 죽네. 동일한 코드가 샘플앱에서 정상동작 하는 것까지 확인했는데,,,흠...

A callback was made on a garbage collected delegate of type

다시 가보고 싶은 리스보아

GC에 의해 해제된 delegate 델리깃에 접근해서 발생하는 Exception

Callback delegates being collected? 질문이 벌써 몇개 있었다. 답변이 아주 간단 명료하다.

That's the problem statement. FMod is unmanaged code. You are creating a delegate object here and passing it to the unmanaged code. Problem is, the garbage collector cannot track references held by native code. The next garbage collection will find no references to the object and collect it. Kaboom when the native code makes the callback.

delegate object를 unmanaged code에 넘겨 주면, garbage collector는 native code의 레퍼런스는 추적할 수 없다! 따라서, native code 이외에 레퍼런스가 없다면, 자연스럽게 garbage collector가 delegate object를 회수해 가고, 이미 회수된 delegate을 invoke하려 했기 때문에 그에 대한 exception을 발생시키는 것이다.

해결 방법은 아주 간단하다. 회수되지 않도록 managed code에 레퍼런스를 생성하면 된다.

간헐적으로 발생하는 고약한 놈!

위의 내용에 대해서는 callbackOnCollectedDelegate MDA 여기에 잘 나와있다. MDA라는 도우미를 통해서 디버깅도 가능한데, 거기까지는 못해봤다. 다만, 해당 글에 자세히 설명이 되어 있어서 도움이 많이 되었다.

Garbage Collector가 수집을 하는 시점은 상황에 따라 다르기 때문에 간헐적으로 발생 할 수 있다. 최악! 샘플앱에서도 재현하기 위해서 의심되는 시점에 강제로 GC.Collect()를 수행해 주었더니 재현이 잘 되었다. 다행이...?