هل يجب وضع Marshal.FreeHglobal في كتلة أخيرًا لضمان التخلص من الموارد؟

StackOverflow https://stackoverflow.com/questions/3525932

سؤال

لدي الكتلة التالية من الكود:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
SomeCommandThatCanThrowAnException();
Marshal.FreeHGlobal(unmanagedPointer);

إذا تم لف الكتلة في محاولة ، ووضع أمر freehglobal في كتلة أخيرًا. (في حالة قيام الأمر الأوسط بإلقاء استثناء).

يبدو أنه من المنطقي أن تمنع أخيرًا تسرب الذاكرة في هذه الحالة ، ولكن من الأمثلة التي وجدتها عبر الإنترنت ، لم يتم استخدامها أخيرًا. ربما يتم التخلص من الموارد تلقائيًا على أي حال (على الرغم من أنها غير مُدارة).

هل كانت مفيدة؟

المحلول

لم يتم إصدار الذاكرة غير المدارة المخصصة لـ Marshal.Allochglobal تلقائيًا.

لذلك وضع marshal.freehglobal في أ finally الكتلة هي في الواقع فكرة جيدة:

IntPtr unmanagedPointer = Marshal.AllocHGlobal(buffer.Length);
try
{
    Marshal.Copy(buffer, 0, unmanagedPointer, buffer.Length);
    SomeCommandThatCanThrowAnException();
}
finally
{
    Marshal.FreeHGlobal(unmanagedPointer);
}

من المحتمل أن تكون الأمثلة التي وجدتها حذف معالجة الأخطاء للإيجاز.


إذا كنت تقوم بتخصيص ذاكرة غير مُدارة لأغراض طويلة الأجل (أي عدم تحريرها في نفس الطريقة) ، فقد تكون مهتمًا بلف المؤشر في كائن مستمد من SafeHandle (مثل SafeBuffer).

SafeHandle ينفذ النمط القابل للاستمتاع ، لذلك سيتم تحرير الذاكرة غير المدارة عند التخلص من الكائن أو عندما يقوم جامع القمامة بجمع الكائن. مستمدة من SafeHandle أيضًا من فئة CriticalizerObject مما يعني أنه سيحصل على علاج خاص من CLR للتأكد من تحرير الذاكرة حقًا.

class HGlobal : SafeBuffer
{
    public HGlobal(int cb)
        : base(true)
    {
        this.SetHandle(Marshal.AllocHGlobal(cb));
        this.Initialize((ulong)cb);
    }

    protected override bool ReleaseHandle()
    {
        Marshal.FreeHGlobal(this.handle);
        return true;
    }
}

مثال:

using (var h = new HGlobal(buffer.Length))
{
    h.WriteArray(0, buffer, 0, buffer.Length);
}

ملاحظة: SafeBuffer هو وحش تمامًا ، لذلك ينصح الحذر.

ملاحظة 2: تعمل SafeHandles بشكل جيد مع P/Invoke والقضاء على الحاجة إلى المرور حول IntPtrs تمامًا.

إن SafeBuffers هي معالجة الذاكرة غير المدارة بأمان من C#، لذلك بناءً على ما تفعله (تخصيص ذاكرة غير مُدارة للاستخدام مع P/invoke ، أو معالجة الذاكرة غير المدارة من C#) ، يجب عليك اختيار SafeHandle أو SafeBuffer كصف أساسي.

نصائح أخرى

قطعاً. هو - هي أبداً يتم إصدارها تلقائيًا ، إنها ذاكرة غير مُدارة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top