سؤال

جريت عبر الخطأ التالية (وجدت الحل على الانترنت, لكنه لم يكن موجودا في تجاوز سعة مكدس):

(.غنو.linkonce.[الاشياء]):غير معرف إشارة إلى [طريقة] [object الملف]:(.غنو.linkonce.[الاشياء]):غير معرف الإشارة إلى `typeinfo على [classname]'

لماذا قد واحدة الحصول على واحد من هذه "undefined الإشارة إلى typeinfo" رابط الأخطاء ؟

(نقاط المكافأة إذا كنت يمكن أن تفسر ما يجري وراء الكواليس.)

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

المحلول

وأحد الأسباب المحتملة هو لأنك تعلن دالة ظاهري دون تحديد ذلك.

عند نعلن ذلك دون تحديد ذلك في وحدة تجميع نفسها، كنت تشير إلى أن انها تعرف مكان آخر - وهذا يعني أن مرحلة رابط محاولة للعثور عليه في إحدى وحدات تجميع أخرى (أو المكتبات)

ومثال تعريف الدالة الظاهري هو:

virtual void fn() { /* insert code here */ }

في هذه الحالة، كنت إرفاق تعريف للإعلان، مما يعني أن رابط لا تحتاج لحلها لاحقا.

وخط

virtual void fn();

ويعلن fn() دون تحديد ذلك، وسوف يتسبب في رسالة الخطأ التي سئل عن.

وانها تشبه الى حد بعيد رمز:

extern int i;
int *pi = &i;

والتي تنص على أن يتم تعريف i صحيح في وحدة تجميع آخر التي يجب حلها في وقت صلة (وإلا pi لا يمكن وضعها لانها عنوان).

نصائح أخرى

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

[<لأ href = "http://web.archive.org/web/20100503172629/http://www.pubbs.net/201004/gcc/25970-linker-error-undefined-reference-to-typeinfo ، للحصول على واحد في مع عدم RTTI-option.html "يختلط =" noreferrer "> مصدر ]

ويحدث هذا عندما أعلن (غير نقية) وظائف افتراضية والهيئات في عداد المفقودين. في تعريف الفئة الخاصة بك، شيئا مثل:

virtual void foo();

ويجب أن تكون محددة (مضمنة أو في ملف مصدر رابط):

virtual void foo() {}

وأو أعلن نقية الظاهري:

virtual void foo() = 0;

دليل دول مجلس التعاون الخليجي :

<اقتباس فقرة>   

لفئات متعددة الأشكال (الطبقات مع وظائف الظاهرية)، يتم كتابة الكائن type_info على طول مع vtable [...] لجميع أنواع أخرى، ونحن نكتب من وجوه type_info عندما يتم استخدامها: عند تطبيق `typeid" ل تعبير، ورمي كائن، أو يشير إلى نوع في بند الصيد أو استثناء المواصفات.

وقليلا في وقت سابق على نفس الصفحة:

<اقتباس فقرة>   

إذا الطبقة تعلن أي غير مضمنة، وظائف افتراضية غير نقية، ويتم اختيار أول واحد باسم "أسلوب رئيسي" لفئة، وينبعث من vtable فقط في وحدة الترجمة حيث يتم تعريف الطريقة الرئيسية.

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

إذا كنت ربط. حتى واحد إلى آخر، ولكن واحدة أكثر إمكانية بتجميع مع "-fvisibility = الخفية" في دول مجلس التعاون الخليجي أو ز ++. إذا بنيت كلا الملفين. لذا مع "-fvisibility = الخفية" والطريقة الرئيسية ليست في نفسه. لذلك كما آخر من تطبيقات وظيفة الظاهري، فإن هذا الأخير لا يرى vtable أو typeinfo من السابق. إلى رابط، وهذا يبدو وكأنه وظيفة افتراضية لم تنفذ (كما في الأجوبة paxdiablo وcdleary ل).

في هذه الحالة، يجب إجراء استثناء لتسليط الضوء على فئة أساسية مع

__attribute__ ((visibility("default")))

وفي تعريف فئة. على سبيل المثال،

class __attribute__ ((visibility("default"))) boom{
    virtual void stick();
}

وهناك حل آخر، وبطبيعة الحال، هو عدم استخدام "-fvisibility = خفية". أن لا تعقيد الأمور بالنسبة للمترجم ورابط، وربما على حساب الأداء التعليمات البرمجية.

والأجوبة السابقة صحيحة، ولكن يمكن أيضا أن يكون سبب هذا الخطأ عن طريق محاولة استخدام typeid على كائن من الفئة التي لديها <م> لا وظائف افتراضية. C ++ RTTI يتطلب vtable، حتى الطبقات التي ترغب في إجراء تحديد نوع على تتطلب دالة الظاهري واحد على الأقل.

إذا كنت تريد اكتب المعلومات للعمل على الدرجة التي كنت لا تريد حقا أية وظائف افتراضية، وجعل المدمر الظاهري.

والحلول الممكنة لرمز التي تتعامل مع RTTI والمكتبات غير RTTI:

وأ) إعادة ترجمة كل شيء مع أي -frtti أو -fno-RTTI
ب) إذا كان أ) ليس من الممكن بالنسبة لك، جرب ما يلي:

وبنيت نفترض libfoo دون RTTI. يستخدم التعليمات البرمجية libfoo ويجمع مع RTTI. إذا كنت تستخدم فئة (فو) في libfoo التي لديها virtuals، أنت من المحتمل أن تصل إلى خطأ وقت الرابط الذي يقول: في عداد المفقودين typeinfo لفو الدرجة

.

وتحديد فئة أخرى (مثل FooAdapter) التي لا يوجد لديه الظاهري وسوف إعادة توجيه المكالمات إلى فو التي تستخدمها.

وترجمة FooAdapter في مكتبة ثابتة الصغيرة التي لا تستخدم RTTI ويعتمد فقط على الرموز libfoo. تقديم رأس لذلك واستخدام ذلك بدلا من ذلك في التعليمات البرمجية (الذي يستخدم RTTI). منذ FooAdapter ليس لديه وظيفة الافتراضية فإنه لن يكون أي typeinfo وعليك أن تكون قادرا على ربط ثنائي الخاص بك. إذا كنت تستخدم الكثير من فئات مختلفة من libfoo، وهذا الحل قد لا تكون مريحة، لكنها بداية.

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

أنا أعمل على مشروع برمجيا باستخدام كل clang++ و g++.لقد كان وجود ربط المسائل باستخدام clang++, ولكن تم الحصول على undefined reference to 'typeinfo for خطأ مع g++.

نقطة مهمة: ربط النظام مع المسائل g++.إذا كنت قائمة المكتبات تريد الارتباط في أمر وهو غير صحيح يمكنك الحصول على typeinfo خطأ.

انظر هذا السؤال لمزيد من التفاصيل على ربط النظام مع gcc/g++.

وعلى غرار مناقشة RTTI، NO-RTTI أعلاه، يمكن أيضا أن تحدث هذه المشكلة إذا كنت تستخدم dynamic_cast وتفشل في تضمين رمز الكائن الذي يحتوي على تطبيق فئة.

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

ورسالة الخطأ رابط لينكس موجهة بشكل صحيح لي أن خط dynamic_cast، ولكن كان لي رسائل سابقة في هذا المنتدى تبحث عن المفقودين تطبيقات وظيفة بدلا من المشكلة الفعلي: في عداد المفقودين رمز الكائن. كان لي مشكلة لاستبدال الدالة الظاهري اكتب في القاعدة وفئة مشتقة، على سبيل المثال isSpecialType الظاهري كثافة العمليات ()، بدلا من استخدام dynamic_cast. هذا الأسلوب تتجنب شرط لربط تنفيذ التعليمات البرمجية كائن لمجرد الحصول على dynamic_cast للعمل بشكل صحيح.

في الفئة الأساسية (فئة قاعدة مجردة) قمت بتعريف المدمر الظاهري وكما لا يمكن أن تعلن المدمر بوصفها وظيفة افتراضية نقية، إما لديك لتحديد ذلك الحق هنا في فئة مجردة، مجرد تعريف وهمية مثل الظاهري ~ قاعدة () {} لن تفعل، أو في أي من فئة مشتقة.

إذا كنت لا تفعل هذا، وسوف ينتهي بك الأمر في "رمز غير معروف" في وقت الارتباط. منذ VMT له الدخول لجميع وظائف افتراضية نقية مع NULL مطابقة كما يقوم بتحديث الجدول تبعا للتنفيذ في فئة مشتقة. ولكن بالنسبة للوظائف غير نقية ولكن افتراضية، فإنه يحتاج إلى تعريف في الوقت الارتباط بحيث يمكن تحديث جدول VMT.

استخدم ج ++ FILT إلى demangle الرمز. مثل $ ج ++ FILT _ZTIN10storageapi8BaseHostE سيتم إخراج شيء من هذا القبيل "typeinfo لstorageapi :: BaseHost".

وحصلت على الكثير من هذه الأخطاء الآن فقط. ما حدث هو أنني تقسيم فئة رأس ملف فقط في ملف الرأس وملف حزب الشعب الكمبودي. ومع ذلك، لم يتم تحديث نظام بناء بلدي، وبالتالي فإن ملف حزب الشعب الكمبودي لم تحصل المترجمة. بين مجرد وجود مراجع غير محددة لمهام أعلن في رأس ولكنها لم تنفذ، وأنا حصلت على الكثير من هذه typeinfo أخطاء.

وكان الحل لإعادة تشغيل النظام بناء لتجميع وربط ملف حزب الشعب الكمبودي الجديد.

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

كما ذكر من قبل @سيرجي ، knowning يمكن أن يكون مشكلة 'rtti', تمكنت من حل بها وضع منشئ التنفيذ في منفصلة .الملف cpp و تطبيق '-fno-rtti' ترجمة الأعلام إلى الملف.أنه يعمل بشكل جيد.

وأنا لا تزال غير واضحة تماما حول الداخلية من هذا الرابط خطأ, لست متأكدا ما إذا كان الحل هو عام.ومع ذلك, أعتقد أنه يستحق رصاصة واحدة قبل أن يحاول محول الطريقة كما ذكرها @فرانسوا .وبطبيعة الحال, إذا كان كل رموز المصدر متوفرة(في حالتي), أفضل ترجمة مع '-frtti' إذا كان ذلك ممكنا.

أكثر شيء واحد ، إذا اخترت لمحاولة الحل ، في محاولة جعل ملف منفصل بسيطة بقدر الإمكان ، وعدم استخدام بعض الميزات الفاخرة من C++.تأخذ اهتماما خاصا على دفعة من الأمور ذات الصلة, يسبب الكثير من ذلك يعتمد على rtti.

ولقد حصلت على نفس الخطأ عندما بلدي واجهة (مع جميع وظائف افتراضية نقية) في حاجة واحدة أكثر من وظيفة وأنا نسيت أن "لاغية" عليه.

وكان

وclass ICommProvider { public: /** * @brief If connection is established, it sends the message into the server. * @param[in] msg - message to be send * @return 0 if success, error otherwise */ virtual int vaSend(const std::string &msg) = 0; /** * @brief If connection is established, it is waiting will server response back. * @param[out] msg is the message received from server * @return 0 if success, error otherwise */ virtual int vaReceive(std::string &msg) = 0; virtual int vaSendRaw(const char *buff, int bufflen) = 0; virtual int vaReceiveRaw(char *buff, int bufflen) = 0; /** * @bief Closes current connection (if needed) after serving * @return 0 if success, error otherwise */ virtual int vaClose(); };

وvaClose آخر ليس الظاهري جمعت حتى لا يعرف أين يمكن الحصول على تنفيذ له، وبالتالي حصل الخلط. كانت رسالتي:

<اقتباس فقرة>   .

و... TCPClient.o :( rodata + 0x38 درجة): إشارة غير محددة إلى `typeinfo لICommProvider '

وتغيير بسيط من

virtual int vaClose();

إلى

virtual int vaClose() = 0;

وإصلاح المشكلة. آمل أن يساعد

وواجهت وضعا هذا أمر نادر الحدوث، ولكن هذا قد يساعد على أصدقاء آخرين في وضع مماثل. ولا بد لي من العمل على نظام القديم مع دول مجلس التعاون الخليجي 4.4.7. لا بد لي من ترجمة التعليمات البرمجية مع c ++ 11 أو فوق مستوى الدعم، ولذا فإنني بناء على أحدث إصدار من دول مجلس التعاون الخليجي 5.3.0. عند بناء قانون بلدي وربط التبعيات إذا كانت التبعية بناء مع مترجم الأكبر سنا، ثم حصلت على "المرجعية غير معرفة ل'خطأ على الرغم من أنني حددت بوضوح مسار الربط مع -L / الطريق / / تحرر -llibname. بعض الحزم مثل دفعة ومشاريع بناء مع cmake عادة لديه ميل لاستخدام مترجم كبار السن، وأنها عادة ما تسبب هذه المشاكل. عليك أن تقطع شوطا طويلا للتأكد من أنها تستخدم مترجم أحدث.

في حالتي هو محض قضية مكتبة التبعية حتى لو كان لدي دعوة dynamic_cast. بعد إضافة ما يكفي من التبعية إلى MAKEFILE ذهب هذه المشكلة.

وتأكد من أن تبعيات الخاص جمعت دون -f-nortti.

لبعض المشاريع لديك لتعيين ذلك صراحة، كما هو الحال في RocksDB:

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