كيف يمكنني معرفة ما الذي يجعل التطبيق الخاص بي يمزج بين CRT المرتبط بشكل ثابت وديناميكي

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

سؤال

آسف على المنشور الطويل الذي يلي.

أعلم أنه ليس من الجيد خلط أوقات تشغيل C و C ++ المرتبطة بشكل ثابت وربط C ++ الذي توفره Microsoft. تطبيقنا في العمل يمزجهم بالفعل لسوء الحظ ونحن نحاول إصلاح ذلك. لأسباب مختلفة (من بينها عدم الإلمام بـ MSI ، فإن حقيقة أننا نستخدم NSIS والتي ربما لا تدعم MSMs جيدًا ، وعدم وجود الوقت والموارد) ، قررنا ربط CRTs بشكل ثابت بدلاً من الديناميكية. أعرف الأسباب التي تجعل هذه ليست فكرة جيدة ، لكنها كانت اختيارنا في الوقت الحالي.


الكود لدينا هو في الغالب قياسي C ++ يكمله الكثير من المكتبات الأخرى مفتوحة المصدر.

هيكل التطبيق هو: الوحدات النمطية المختلفة التي تؤدي إلى مكتبات ثابتة ترتبط نفسها معًا لإنشاء أشياء مختلفة من بينها واحدة قابلة للتنفيذ تمنحنا مشاكل.

في الإصدار نحن نبني كل شيء لنا رمز مع /MT. بالنسبة لبعض المكتبات المفتوحة المصدر ، استخدمنا الثنائيات المسبقة وبعضها تم تجميعها مع /MD مما جعلنا نخلط أوقات التشغيل. لذلك قمنا بإعادة ترجمة أولئك أنفسنا مع /MT وجعلناها تؤدي إلى مكتبات ثابتة وليس DLLs. لم يتم هذا التحويل لكل مكتبة ، لذلك ما زلنا نربط مع بعض DLLs التي تستخدم /MD.


والنتيجة الآن هي أنه في comps.exe كل الأشياء لدينا باستثناء واحد قابل للتنفيذ لا مباشرة تعتمد على msvcr80.dll أو msvcp80.dll. بواسطة لا يعتمد بشكل مباشر أعني أن msvcr80.dll ليس طفلًا من جذر الشجرة الموضح بواسطة comps.exe. في بعض الأحيان ، نجد msvcr80.dll يتم سحبها بواسطة أحد DLLs المكتبة ولكن هذه بعض المستويات أعمق في الشجرة.

كيف يمكنني معرفة لماذا MSVCR80.dll على المستوى الأول لهذا المزعج القابل للتنفيذ؟ ما الذي يجعل هذا الرابط القابل للتنفيذ مباشرة إلى msvcr80.dll؟

قد يكون أحد الأسباب هو أننا نربط بشكل ثابت بالمكتبة A التي تستخدمها /MD بحيث تربط ديناميكيًا مع CRT. لذلك ينتهي الرمز في المكتبة A في قابلة للتنفيذ لدينا ، بحيث روابط قابلة للتنفيذ مع msvcr80.dll. ولكن كيف يمكنني معرفة أي من المكتبات تفعل ذلك؟


ما جربته حتى الآن:

  • قم بتحميل ملفات .lib المرتبطة بشكل ثابت في comps.exe -> لا تعمل لأن comps.exe تتوقع أن يكون DLL قابلة للتنفيذ أو DLL وليس مكتبة ثابتة
  • استخدم dumpbin.exe /التوجيهات على ملفات .lib المرتبطة بشكل ثابت -> لم يظهر أي منهم msvcrt80.dll (أثناء وجوده في التصحيح ، حيث نحاول استخدام /mdd لكل شيء ، فقد أظهروا msvcrt80d.dll مما يجعلني أعتقد أن الطريقة هي جيد ويثبت أنه يتم تجميع جميع المكتبات ذات المصدر المفتوح المرتبطة بشكل صحيح مع /mT)
  • استخدم /ferbose: lib linker flag -> لقد أظهر أنه في الواقع يتم سحبه في msvcrt.lib وهي مكتبة الاستيراد لـ msvcr80.dll لذلك نحن في مشكلة ولكنها لم تقل سبب قيامها بذلك
  • استخدم علامة الارتباط /ferbose + في Visual Studio: تبعيات إضافية libcmt.lib + تجاهل جميع المكتبات الافتراضية نعم + تجاهل مكتبة محددة: msvcrt.lib في محاولة يائسة لجعل msvcrt.lib تختفي أو ترى من يسحبها. النتيجة صدمتني:
    Searching C:\Program Files\Microsoft Visual Studio 8\VC\lib\msvcrt.lib:  
      Found "public: virtual void * __thiscall type_info::`vector deleting destructor'(unsigned int)" (??_Etype_info@@UAEPAXI@Z)  
        Referenced in libcmt.lib(typinfo.obj)  
        Loaded msvcrt.lib(ti_inst.obj)  
            msvcrt.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(class type_info const &)" (??0type_info@@AAE@ABV0@@Z) already defined in libcmt.lib(typinfo.obj)  
            msvcrt.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_info::operator=(class type_info const &)" (??4type_info@@AAEAAV0@ABV0@@Z) already defined in libcmt.lib(typinfo.obj)  
      Found "void __stdcall `eh vector destructor iterator'(void *,unsigned int,int,void (__thiscall*)(void *))" (??_M@YGXPAXIHP6EX0@Z@Z)  
        Referenced in msvcrt.lib(ti_inst.obj)
        Loaded msvcrt.lib(ehvecdtr.obj)

بقدر ما أفهم ، typinfo.obj في libcmt.lib يشير إلى رمز ، والبحث في msvcrt.lib وبعد أن يجد في ti_inst.obj يلقي خطأ أنه محدد مرتين. لكن هذا لا معنى له. إذا كان libcmt.lib لديه بالفعل رمز لماذا ينتهي به الأمر إلى البحث عنه في msvcrt.lib وبالتالي جلب msvcr80.dll في بلدي القابل للتنفيذ؟ وبشكل عام ، لماذا تبحث المكتبة الثابتة عن الرموز في مكتبة الاستيراد الديناميكية؟ لماذا ينظر الرابط حتى إلى msvcrt.lib إذا كان لدي في مكتبة تجاهل محددة؟

شكرا لصبرك :-).

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

المحلول

لدي حل لمشكلتي. لقد كان خطأ غبي ترك هناك من العصور القديمة على الأرجح.

تم ذكر msvcrt.lib صراحة من قبلنا في مربع التبعيات الإضافية: --( لذلك بالطبع جعل DLL تبعية. وبسبب جميع المكتبات المفتوحة المصدر هذا المربع يحتوي على الكثير من النص ، لذلك لم نلاحظ ذلك. ولكي نكون صادقين ، لم نفكر في النظر إلى هذا المربع بعناية لأننا لم نتخيل أنه قد يكون هناك مثل هذا الخطأ الجسيم في مشاريعنا.

نصائح أخرى

افتح قابلاً للتنفيذ مع comps.exe وقم بتشغيل profiler المدمج فيه يعتمد. أعتقد أن هذا سيسجل سبب تحميل جميع DLL الخاص بك ، ومن حيث يتم تحميلها. راجع خيار "Log LoadLibrary Calls".

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