يكون &[تي] حرفيا اسم مستعار لشريحة في الصدأ?

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

  •  21-12-2019
  •  | 
  •  

سؤال

&[T] هو الخلط لي.

افترضت بسذاجة أن مثل &T, &[T] كان المؤشر, ، أي عنوان مؤشر رقمي.

ومع ذلك ، لقد رأيت بعض التعليمات البرمجية مثل هذا ، أنني فوجئت إلى حد ما لرؤية العمل بشكل جيد (مبسطة لأغراض العرض التوضيحي;ولكن ترى رمز مثل هذا في العديد من' أس شريحة () ' تطبيقات):

extern crate core;
extern crate collections;

use self::collections::str::raw::from_utf8;
use self::core::raw::Slice;
use std::mem::transmute;

fn main() {
  let val = "Hello World";
  {
    let value:&str;
    {
      let bytes = val.as_bytes();
      let mut slice = Slice { data: &bytes[0] as *const u8, len: bytes.len() };
      unsafe {
        let array:&[u8] = transmute(slice);
        value = from_utf8(array);
      }
      // slice.len = 0;
    }
    println!("{}", value);
  }
}

لذا.

اعتقدت في البداية أن هذا رمز غير صالح.

وهذا هو ، على سبيل المثال من Slice تم إنشاؤه داخل نطاق الكتلة يتم إرجاعه إلى خارج نطاق الكتلة (عن طريق التحويل) ، وعلى الرغم من تشغيل الكود ، فإن println! هو في الواقع الوصول إلى البيانات التي لم تعد صالحة من خلال مؤشرات غير آمنة.سيئة!

...لكن لا يبدو أن هذا هو الحال.

النظر في التعليق على الخط // slice.len = 0;

هذا الرمز لا يزال يعمل بشكل جيد (يطبع 'مرحبا العالم') عندما يحدث هذا.

وبالتالي فإن الخط...

value = from_utf8(array);

إذا كان مؤشر غير صالح إلى متغير 'شريحة' ، فإن len في ال println() سيكون البيان 0 ، لكنه ليس كذلك.على نحو فعال نسخة ليس فقط من قيمة المؤشر ، ولكن نسخة كاملة من Slice هيكل.

هل هذا صحيح?

هل هذا يعني أنه بشكل عام صالح للعودة أ &[T] طالما أن مؤشر البيانات الداخلية الفعلي صالح ، بغض النظر عن نطاق الأصلي &[T] يتم إرجاع ذلك ، لأن أ &[T] الاحالة هي عملية نسخة?

(يبدو لي أن هذا أمر بديهي للغاية...لذلك ربما أنا سوء فهم;إذا أنا على حق ، وجود اثنين &[T] هذه النقطة إلى نفس البيانات لا يمكن أن تكون صالحة ، لأنها لن مزامنة أطوال إذا قمت بتعديل واحد...)

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

المحلول

شريحة &[T], ، كما لاحظت ،هو" مكافئ " للهيكل std::raw::Slice.في الواقع, Slice هو تمثيل داخلي لـ &[T] القيمة ، ونعم ، هو مؤشر وطول البيانات وراء هذا المؤشر.في بعض الأحيان يسمى هذا الهيكل "مؤشر الدهون" ، وهذا هو ، مؤشر وقطعة إضافية من المعلومات.

عندما تمر &[T] قيمة حولها ، كنت في الواقع مجرد نسخ محتوياته-المؤشر والطول.

إذا كان مؤشر غير صالح لمتغير 'شريحة' ، فإن لين في بيان برينتلن() سيكون 0 ، لكنه ليس كذلك.على نحو فعال نسخة ليس فقط من قيمة المؤشر ، ولكن نسخة كاملة من هيكل شريحة.هل هذا صحيح?

لذا ، نعم ، بالضبط.

هل هذا يعني أنه بشكل عام صالحة للعودة &[ر] طالما أن مؤشر البيانات الداخلية الفعلي صالح, بغض النظر عن نطاق الأصلي & [ر] التي يتم إرجاعها, لأن &[ر] الاحالة هي عملية نسخة?

وهذا صحيح أيضا.هذه هي الفكرة الكاملة للمراجع المستعارة ، بما في ذلك الشرائح - يتم فحص المراجع المستعارة بشكل ثابت لاستخدامها طالما أن مرجعها على قيد الحياة.عندما يهبط التوقيت الصيفي أخيرا ، ستكون الشرائح والمراجع العادية أكثر توحيدا.

(يبدو لي أن هذا أمر بديهي للغاية...لذلك ربما أنا سوء فهم;إذا كنت على حق ، فإن وجود اثنين و[ر] يشيران إلى نفس البيانات لا يمكن أن يكون صالحا ، لأنهما لن يتزامنا الأطوال إذا قمت بتعديل واحدة...)

وهذا في الواقع مصدر قلق صحيح تماما;انها واحدة من المشاكل مع التعرج.ومع ذلك ، تم تصميم الصدأ بالضبط لمنع مثل هذه الأخطاء.هناك نوعان من الأشياء التي تجعل التعرج من شرائح صالحة.

أولا ، لا يمكن للشرائح تغيير الطول;لا توجد طرق محددة على &[T] مما يسمح لك بتغيير طوله في مكانه.يمكنك إنشاء شريحة مشتقة من شريحة ، لكنها ستكون كائنا جديدا على الإطلاق.

ولكن حتى إذا لم تتمكن الشرائح من تغيير الطول ، إذا كان من الممكن تحور البيانات من خلالها ، فإنها لا تزال قادرة على إحداث كارثة إذا تم تسميتها.على سبيل المثال ، إذا كانت القيم في الشرائح مثيلات تعداد ، فإن تغيير قيمة في مثل هذه الشريحة المستعارة قد يجعل المؤشر إلى الأجزاء الداخلية لقيمة التعداد الموجودة في هذه الشريحة غير صالح.لذلك ، ثانيا ، شرائح الصدأ المستعارة (&[T]) غير قابلة للتغيير.لا يمكنك تغيير القيم الواردة فيها ولا يمكنك أخذ مراجع قابلة للتغيير فيها.

هذه الميزات اثنين (والشيكات مترجم لأعمار) جعل التعرج من شرائح آمنة تماما.ومع ذلك ، في بعض الأحيان تحتاج إلى تعديل البيانات في شريحة.ثم تحتاج قابل للتغيير شريحة ، ودعا &mut [T].يمكنك تغيير البيانات الخاصة بك من خلال هذه الشريحة;لكن هذه الشرائح هي غير مستعارة.لا يمكنك إنشاء شريحتين قابلتين للتغيير في نفس البنية (مصفوفة ، على سبيل المثال) ، لذلك لا يمكنك فعل أي شيء خطير.

لاحظ ، مع ذلك ، أن استخدام transmute() لتحويل شريحة إلى Slice أو العكس هو عملية غير آمنة. &[T] مضمون بشكل ثابت ليكون صحيحا إذا قمت بإنشائه باستخدام الطرق الصحيحة ، مثل الاتصال as_slice() على Vec.ومع ذلك ، إنشائه يدويا باستخدام Slice هيكل ومن ثم تحويلها إلى &[T] هو عرضة للخطأ ويمكن بسهولة سيغفولت البرنامج الخاص بك ، على سبيل المثال ، عند تعيينه أكثر طول مما هو مخصص في الواقع.

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