Instances added to NativeToManagedMaps are never removed
dimozaprianov opened this issue · 4 comments
This results in in memory leak
Thank you for the report. Can you please provide a code example or point to a specific instance where this is the case? I am looking through the code paths and I don't see any paths where instances can be created, added to the static NativeToManagedMap and then not removed when disposed.
Look at the FpdfDocumentT for example. When we create an object it is kept in the NativeToManagedMap. But then I cannot see anywhere it is removed. There are classes that are Disposable that have this issue handled correctly. Excuse me if I'm missing something here.
Regarding the FpdfDocumentT
class, can you please provide a code path which adds an instance instances to the NativeToManagedMap
static field? I see the following paths, none of which are invoked in the library in a way that will add the instance to the NativeToManagedMap
, and all of them are marked internal or private so they should never be invoked.
Note, this is also true the following basic instance reference classes and more: FpdfActionT
, FpdfAnnotationT
, FpdfAttachmentT
, FpdfAvailT
, etc...
1.
private FpdfDocumentT(__Internal native, bool skipVTables = false)
: this(__CopyValue(native), skipVTables)
{
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
}
2.
internal static FpdfDocumentT __CreateInstance(__Internal native, bool skipVTables = false)
{
return new FpdfDocumentT(native, skipVTables);
}
3.
internal static FpdfDocumentT __GetOrCreateInstance(__IntPtr native, bool saveInstance = false, bool skipVTables = false)
{
if (native == __IntPtr.Zero)
return null;
if (NativeToManagedMap.TryGetValue(native, out var managed))
return (FpdfDocumentT)managed;
var result = __CreateInstance(native, skipVTables);
if (saveInstance)
NativeToManagedMap[native] = result;
return result;
}
- Private constructor adds the current instance to the NativeToManagedMap. Only invoked from code block 2.
- Factory method in code block 2 is never invoked by the library and is internal, so it should never be invoked.
- Factory method in code block 3 doesn't touch the NativeToManagedMap static field in any of the library invocations.
Ultimately, it seems the static field NativeToManagedMap
is never used on these objects and should not exist in the generated code, but I don't see a method to prevent the map from being generated on these few classes which only are used for passing the C++ reference around.
NativeToManagedMap
is used in other areas but those classes mostly have IDisposable
which will remove the instance from the map.
Going to close this issue until a specific code path can be brought to my attention.