Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
97 views
in Technique[技术] by (71.8m points)

.net - Do I need to clean up unmanaged code after obtaining an IStorage object from OLE32?

I obtain an IStorage object from OLE32's StgCreateStorageEx function. Here is its declaration:

Imports Microsoft.VisualStudio.OLE.Interop

<System.Runtime.InteropServices.DllImport("ole32.dll",
    SetLastError:=True, CharSet:=CharSet.Unicode)>
Private Shared Function StgCreateStorageEx(
    <MarshalAs(UnmanagedType.LPWStr)>
        ByVal pwcsName As String,
    ByVal grfMode As UInt32,
    ByVal stgFmt As UInt32,
    ByVal grfAttrs As UInt32,
    ByRef pStgOptions As SStgOptions,
    ByVal pSecurityDescriptor As IntPtr,
    <[In]()> ByRef riid As Guid,
    <[Out]()> ByRef ppObjectOpen As IStorage) As Int32
End Function

The caller sets the flags and the structure member, then obtains a new IStorage object in an oStorage As IStorage object. So far all is well.

The documentation kindly reminds us:

An application must release its IStorage pointers when it is done with the storage object to deallocate memory used.

Since the object was created by COM and consumes memory, and since we all don't like memory leaks, the standard thing to do would be to properly implement IDisposable and dispose of the caller's oStorage object, via the Marshal.ReleaseComObject(oStorage) method. But...

I happened to come across this document Marshal.ReleaseComObject Considered Dangerous, by the Visual Studio developers. Only that...

I am not sure if I understand the causes thoroughly. However, it seems to be a clear advice to stay away from ReleaseComObject altogether. But...

The document stems from 2010. Is this still the proper advice, more than a decade later? And...

How would I otherwise prevent memory leaks?

question from:https://stackoverflow.com/questions/65847046/do-i-need-to-clean-up-unmanaged-code-after-obtaining-an-istorage-object-from-ole

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Maybe this should be in comments...

The answer is that the framework does do the Release() for you. But, it does it in a non-deterministic fashion. It will do it in a garbage collection cycle when the criteria for cleaning it up is made.

If you are using the code in a block and you are sure you are not passing any other references to the storage to be saved for later use, my personal recommendation based on years of experience is to go call Marshal.ReleaseComObject() with the oStorage object. Of course, if you open any streams or other sub storages, make sure you close and release those objects first. If any of the streams or sub storages you open are saved for later use, then don't release the main storage.

If you open a storage and then do nothing--you let the framework call it eventually--if you try to open the storage again and the framework hasn't destroyed the previous object, it may be possible that the call to a function to open the storage again will fail. It might fail because of permissions issues because it is already open...open because it hasn't been released by the framework yet in a GC cycle.

YMMV


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...