[Mono-dev] OracleClient.Oci and GC

Neale Ferguson NealeFerguson at verizon.net
Mon Aug 25 15:08:07 UTC 2014


I implemented a Dispose method for OracleParameter:

                ~OracleParameter ()
                {
                        Dispose(false);
                }

                public void Dispose ()
                {
                        Dispose (true);
                }

                void Dispose (bool disposing)
                {
                        if (disposing) {
                                GC.SuppressFinalize(this);
                        }
                        if (indicator != IntPtr.Zero) {
                                Marshal.FreeHGlobal (indicator);
                                indicator = IntPtr.Zero;
                        }
                }

However, when I run the test program I see 1251 constructors being run but only 572 destructors/disposals. How do I reconcile this disparity?

Neale

On Aug 22, 2014, at 11:40 AM, Neale Ferguson <NealeFerguson at verizon.net> wrote:

> Thanks. I've made changes to OciDefineHandle and have cured nearly all the failures I had been experiencing. I have started on OracleParameter as it has an object called indicator that is used by the OCIBindxxx calls and appears to suffer from the same problem. I was allocating the object in native memory in the constructors and was going to free them in a destructor. However, in my test runs I see I'm allocating 1200+ objects but only freeing ~900. Would you elaborate on your final comment "failing to dispose..." as I'm reading this as I don't need to Marshal.FreeHGlobal() the object I allocated in the constructors.
> 
> Neale
> 
> On Aug 22, 2014, at 11:31 AM, Rodrigo Kumpera <kumpera at gmail.com> wrote:
> 
>> Hey Neale,
>> 
>> You can safely pass interior pointers to pinvoke without fearing the object been collected for the duration of the call.
>> Mind that you have to correctly use specify in/out/ref depending on the copy semantics you need.
>> 
>> Problems only arise when native keeps that pointer after the call finishes, this can result in the object been moved
>> as the GC has no visibility into the native heap.
>> 
>> For those cases you can either create a pinning GC handle to the victim object or you can allocate a chunk of native
>> memory that will be shared between managed and native to store the desired value. Both options suck, TBH.
>> 
>> I'd say go with the native chunk of code if you can't lexically scope the pinning regions, it will be more reliable as
>> failing to dispose the object won't lead to permanent leaks.



More information about the Mono-devel-list mailing list