هل من الآمن استخدام المحكمة الخاصة بلبنان (TR1) shared_ptr بين وحدات (exes و dlls)
-
19-08-2019 - |
سؤال
وأنا أعلم أن الجديد-ing شيء في وحدة واحدة وحذف جي في آخر كثير من الأحيان يمكن أن يسبب مشاكل في VC++.مشاكل مع مختلف أوقات التشغيل.خلط وحدات مع staticly ربط أوقات التشغيل و/أو مرتبطة بشكل حيوي الإصدارات التطابق على حد سواء يمكن أن المسمار الأشياء إذا كنت أتذكر بشكل صحيح.
ولكن هل من الآمن استخدام VC++ 2008 std::tr1::shared_ptr عبر وحدات?
لأنه ليس هناك نسخة واحدة فقط من وقت التشغيل الذي يعرف حتى ما shared_ptr هو ثابت ربط هو الخطر الوحيد (حتى الآن).ظننت أنني قرأت أن دفعة نسخة shared_ptr كان من الآمن استخدام مثل هذا, ولكن أنا باستخدام ريدموند الإصدار...
أنا في محاولة لتجنب الاضطرار خاصة إلى الكائنات في تخصيص وحدة.(أو شيء من هذا القبيل "حذف" في الصف نفسه).إذا كان كل هذا يبدو قليلا hacky, أنا باستخدام هذا اختبار وحدة.إذا كنت قد حاولت من أي وقت مضى إلى وحدة اختبار القائمة رمز C++ هل يمكن أن نفهم كيف الإبداعية عليك أن تكون في بعض الأحيان.ذاكرتي التي خصصتها EXE ولكن في نهاية المطاف سوف يكون الافراج في DLL (إذا كان المرجع عد يعمل بالطريقة التي أعتقد أنها لا).
المحلول
تحرير الذاكرة بأمان طالما أنه جاء من نفس إدارة الذاكرة السياق.كنت قد حددت المشكلة الأكثر شيوعا (مختلف C++ أوقات التشغيل);وجود أكوام منفصلة أخرى أقل شيوعا المشكلة التي يمكن أن تصل إلى.
مسألة أخرى لم تذكر ، ولكن الذي يمكن أن يكون exascerbated المشتركة المؤشرات ، هو عندما كائن هو رمز موجود في DLL و يتم إنشاؤه من قبل DLL, ولكن كائن آخر خارج DLL ينتهي مع إشارة إلى أنه (طريق مشترك المؤشر).إذا كان هذا الكائن هو تدميرها بعد DLL يتم تفريغ (على سبيل المثال ، إذا كان مستوى الوحدة النمطية الساكنة ، أو إذا كان DLL صراحة تفريغها من قبل FreeLibrary()
, المشتركة الكائن المدمر سوف تحطم الطائرة.
هذا يمكن لدغة لك إذا كنت تحاول كتابة DLL المستندة إلى جانب فضفاضة الإضافات.وهو أيضا السبب الذي COM يتيح DLLs تقرر عند يمكن يتم تفريغ, بدلا من السماح ملقمات COM الطلب يفرغ منها.
نصائح أخرى
لقد بدأت أرى كيف مذهلة بشكل لا يصدق shared_ptr
هو :)
كونها آمنة عبر DLL الحدود هو بالضبط ما shared_ptr
صمم ليكون (من بين أمور أخرى, بالطبع).
على عكس ما قاله الآخرون, حتى أنك لا تحتاج إلى تمرير العرف deleter عند بناء shared_ptr
, كما الافتراضي هو بالفعل شيء مثل
template <typename T>
struct default_deleter {
void operator()( T * t ) { delete t; }
};
و
shared_ptr<Foo> foo( new Bar );
ما يعادل
shared_ptr<Foo> foo( new Bar, default_deleter<Bar>() );
(ie.لا يوجد شيء مثل shared_ptr
دون deleter).
بسبب نوع المحو التي أجريت على deleter ، delete
يسمى هذا سوف دائما تكون واحدة من DLL إنشاء مثيل على shared_ptr
, أبدا واحد من DLL حيث الماضي shared_ptr
يخرج من نطاق (ie.على shared_ptr
الاحتجاج deleter سوف يطلق عليه من خلال مؤشر على وظيفة وضعت هناك من قبل الأصلي shared_ptr
).
قارن هذا إلى auto_ptr
, الذي يضمن delete
المشغل مباشرة في (مضمنة) المدمر ، مما يعني أن delete
DLL يدمر على auto_ptr
يستخدم خلق نفس المشاكل حذف عارية المؤشر.
من قبل نفس تقنية متعددة الأشكال الطبقات التي هي دائما في shared_ptr
s لا تحتاج حتى الظاهري المدمر ، لأن deleter دائما ندعو حق المدمر ، حتى حين آخر shared_ptr
إلى الخروج من نطاق واحد مثيل لهذه الفئة الأساسية.
إذا كنت قلقا ، استخدام شكل shared_ptr منشئ أن يأخذ deleter الحجة.على deleter يمكن أن ندعو مرة أخرى إلى الوحدة النمطية التي خصصت الكائن بحيث يتم حذف يحدث في السياق الصحيح.
دفعة وثائق يدعي أنه هو 100 ٪ متوافق مع TR1, لذلك نأمل أن لا يوجد شيء مضللة حول هذا:
http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm#constructors
أعتقد أنها آمنة كما أن استخدام أي من الفئات في std
عبر وحدات.
وهذا هو:يجب أن تكون آمنة إذا كانت وحدات استخدام نفس مكتبة وقت تشغيل و بالضبط نفس رموز تبديل برنامج التحويل البرمجي و الخيارات.
أبدا استخدام ثابت مكتبة وقت التشغيل ، حيث أن كل وحدة سوف تحصل على الدرجة الخاصة من جميع globals داخلها.
أفضل نصيحة رأيت في الموضوع هو أن الذاكرة يجب أن يكون deallocated في نفس السياق انه المخصصة.هذا لا يمنع مكتبة يمر الظهر مؤشر على أن تطبيق قانون يفترض مجانا ومع ذلك, لذلك أنا أقول ربما كنت آمنة اجتياز shared_ptr في هذه الطريقة ، كما إنها نفس الحالة العامة.
إذا دلالات النظام الخاص بك يعني أن المؤشر هو في الواقع نقل (في ملكية الشعور) من exe dll الخاص بك ، ثم auto_ptr قد يكون أفضل حل.ومع ذلك ، إذا كان المؤشر الخاص بك هو حقا المشتركة ، ثم shared_ptr هو على الارجح أفضل حل.