سؤال

Plugin1.cpp:

#include <iostream>

static class TestStatic {
public:
  TestStatic() {
     std::cout << "TestStatic create" << std::endl;
  }
  ~TestStatic() {
     std::cout << "TestStatic destroy" << std::endl;
  }
} test_static;

Host.cpp

#include <dlfcn.h>
#include <iostream>
int main(int argc,char *argv[]) {
   void* handle = dlopen("./plugin1.so",RTLD_NOW | RTLD_LOCAL );
   dlclose(handle);
   return 0;
}

بناء وتشغيل:

>g++ -c plugin1.cpp -o plugin1.o -fPIC
>g++ -shared plugin.o -o plugin1.so
>g++ host.cpp -o host -ldl
>./host
>TestStatic create
>Segmentation fault

لماذا TestStatic :: ~ testStatic يسمى في "Exit ()" ولكن ليس في "dlClose ()"؟

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

المحلول

يتطلب معيار C ++ أن يتم استدعاء المدمرين للكائنات العالمية عندما يخرج البرنامج بترتيب معاكس للبناء. تعاملت معظم التطبيقات مع هذا من خلال استدعاء مكتبة C atexit روتين لتسجيل المدمرين. هذا مشكلة لأن معيار 1999 C فقط يتطلب أن يدعم التنفيذ 32 وظيفة مسجلة ، على الرغم من أن معظم التطبيقات تدعم الكثير. والأهم من ذلك ، أنه لا يتعامل على الإطلاق مع القدرة في معظم التطبيقات على إزالة DSOs من صورة برنامج قيد التشغيل عن طريق الاتصال بـ DLClose قبل إنهاء البرنامج.

تتم معالجة هذه المشكلة في الإصدارات اللاحقة من مجلس التعاون الخليجي بما في ذلك المكتبة والرابط القياسي C/C ++. في الأساس ، يجب تسجيل المدمرات C ++ باستخدام __cxa_atexit وظيفة بدلا من atexit (3).

للحصول على التفاصيل الفنية الكاملة على __cxa_atexit, ، نرى مواصفات Itanium C ++ ABI.


ليس من الواضح من سؤالك ما هو إصدار GCC و Linker ومكتبة C القياسية التي تستخدمها. بالإضافة إلى ذلك ، لا يلتقي الرمز الذي قدمته Posix المعيار حيث لا يوجد RTDL_NOW أو RTDL_LOCAL وحدات الماكرو المحددة. هم انهم RTLD_NOW و RTLD_LOCAL (نرى dlopen).

إذا كانت المكتبة القياسية الخاصة بك لا تدعم __cxa_atexit, ، قد تحتاج إلى تعطيله من خلال تحديد -fno-use-cxa-atexit علم مجلس التعاون الخليجي:

-fuse-cxa-atexit

قم بتسجيل المدمرات للكائنات ذات مدة التخزين الثابتة مع وظيفة __CXA_ atexit بدلاً من وظيفة ATEXIT. هذا الخيار مطلوب للتعامل مع المدمرات الثابتة المتوافقة مع المعايير بالكامل ، ولكنه لن يعمل إلا إذا دعمت مكتبة C __CXA_ATEXIT.

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

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