سؤال

هل يمكن لأي شخص أن يعطي مثالاً على الوقت المناسب لاستخدام "غير الآمن" و"الثابت" في كود C#؟لقد لعبت بها من قبل، ولكن لم أجد في الواقع استخدامًا جيدًا لها.

خذ بعين الاعتبار هذا الكود...

fixed (byte* pSrc = src, pDst = dst) {
    //Code that copies the bytes in a loop
}

بالمقارنة مع مجرد استخدام...

Array.Copy(source, target, source.Length);

والثاني هو الكود الموجود في .NET Framework، وهو الجزء الأول من الكود المنسوخ من موقع مايكروسوفت على الويب، http://msdn.microsoft.com/en-us/library/28k1s2k6(VS.80).aspx.

يعد Array.Copy() المدمج أسرع بشكل كبير من استخدام التعليمات البرمجية غير الآمنة.قد يكون هذا فقط لأن الثاني مكتوب بشكل أفضل والأول مجرد مثال، ولكن ما أنواع المواقف التي قد تحتاجها حقًا لاستخدام رمز غير آمن/ثابت لأي شيء؟أم أن مطور الويب المسكين هذا يعبث بشيء فوق رأسه؟

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

المحلول

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

إذا كنت تستخدم P/Invoc، فسيقوم المنظم الافتراضي بتثبيت الكائنات نيابةً عنك.في بعض الأحيان يكون من الضروري إجراء تنظيم مخصص، وفي بعض الأحيان يكون من الضروري تثبيت كائن لفترة أطول من مدة استدعاء P/Invine واحد.

نصائح أخرى

لقد استخدمت كتلًا غير آمنة لمعالجة بيانات الصورة النقطية.يعد الوصول إلى المؤشر الأولي أسرع بكثير من SetPixel/GetPixel.

unsafe
{
    BitmapData bmData = bm.LockBits(...)
    byte *bits = (byte*)pixels.ToPointer();
    // Do stuff with bits
}

عادةً ما يتم استخدام "ثابت" و"غير آمن" عند إجراء التشغيل المتداخل أو عند الحاجة إلى أداء إضافي.أي.يستخدم String.CopyTo() طريقة غير آمنة وثابتة في تنفيذها.

سلوك نمط reinterpret_cast

إذا كنت تتلاعب قليلاً، فقد يكون هذا مفيدًا بشكل لا يصدق

تستخدم العديد من تطبيقات كود التجزئة عالية الأداء UInt32 لقيمة التجزئة (وهذا يجعل التحولات أسهل).نظرًا لأن .Net يتطلب Int32 للطريقة التي تريد تحويل uint بسرعة إلى int.نظرًا لأنه لا يهم ما هي القيمة الفعلية، فقط يتم الحفاظ على جميع البتات في القيمة، ومن المرغوب فيه إعادة تفسيرها.

public static unsafe int UInt32ToInt32Bits(uint x)
{
    return *((int*)(void*)&x);
}

لاحظ أن التسمية تمت على غرار BitConverter.DoubleToInt64Bits

بالاستمرار في أسلوب التجزئة، يتيح تحويل البنية القائمة على المكدس إلى بايت* سهولة استخدام وظائف التجزئة لكل بايت:

// from the Jenkins one at a time hash function
private static unsafe void Hash(byte* data, int len, ref uint hash)
{
    for (int i = 0; i < len; i++)
    {
        hash += data[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }
}

public unsafe static void HashCombine(ref uint sofar, long data)
{
    byte* dataBytes = (byte*)(void*)&data;
    AddToHash(dataBytes, sizeof(long), ref sofar);
}

يتيح لك unsafe أيضًا (من الإصدار 2.0 فصاعدًا) استخدام Stackalloc.يمكن أن يكون هذا مفيدًا جدًا في مواقف الأداء العالي حيث تكون هناك حاجة إلى بعض المصفوفات الصغيرة ذات الطول المتغير مثل المساحة المؤقتة.

ستكون كل هذه الاستخدامات ثابتة في "فقط إذا كان تطبيقك يحتاج حقًا إلى الأداء" وبالتالي فهي غير مناسبة للاستخدام العام، ولكن في بعض الأحيان تحتاج إليه حقًا.

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

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

كان علينا استخدام حل ثابت عند تمرير عنوان إلى ملف C DLL القديم.نظرًا لأن DLL يحتفظ بمؤشر داخلي عبر استدعاءات الوظائف، فسوف ينفجر كل شيء إذا قام GC بضغط الكومة ونقل الأشياء.

أعتقد أنه يتم استخدام تعليمات برمجية غير آمنة إذا كنت تريد الوصول إلى شيء ما خارج وقت تشغيل .NET، على سبيل المثال.إنه ليس رمزًا مُدارًا (لا يوجد تجميع للقمامة وما إلى ذلك).يتضمن ذلك مكالمات أولية إلى Windows API وكل موسيقى الجاز هذه.

يخبرني هذا أن مصممي إطار عمل .NET قاموا بعمل جيد في تغطية مساحة المشكلة - والتأكد من أن بيئة "التعليمات البرمجية المُدارة" يمكنها القيام بكل شيء بشكل تقليدي (على سبيل المثال.يمكن أن يفعل نهج C++) التعليمات البرمجية/المؤشرات غير الآمنة.وفي حالة عدم إمكانية ذلك، فإن الميزات غير الآمنة/الثابتة موجودة إذا كنت في حاجة إليها.أنا متأكد من أن شخصًا ما لديه مثال حيث تكون هناك حاجة إلى تعليمات برمجية غير آمنة، ولكن يبدو الأمر نادرًا في الممارسة العملية - وهذا هو بيت القصيد، أليس كذلك؟:)

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