выгрузить статическую переменную экземпляра в плагин c ++? - PullRequest
0 голосов
/ 30 ноября 2011

Заранее спасибо.Сейчас я разрабатываю плагин для большой системы на C ++.В моем плагине у меня есть некоторая статическая переменная.Я обнаружил, что когда он компилируется в режиме отладки в Linux, он работает без проблем.Когда он компилируется в режиме RELEASE, а именно некоторая оптимизация выполняется компилятором, то когда я выгружаю плагин, статическая переменная не удаляется (деструктор класса статических переменных никогда не вызывается.), Поэтому память никогда не освобождается ив следующий раз, когда я перезагружаю плагин, он вызывает основной сбой программы!

Может кто-нибудь объяснить мне, почему статическая переменная не уничтожается при выгрузке плагина?ПРИМЕЧАНИЕ: статическая переменная является статическим экземпляром, а не указателем!

class MySettings
{
   public:
      static MySettings& Instance() {
         static MySettings theSingleton;
         return theSingleton;
      }

      virtual ~MySettings();
}

где-то в плагине, она называется так:

....
MySettings &s = MySettings::Instance();
s.xxx();
....

Когда я скомпилировал и запустил в режим отладки , я распечатал некоторую информацию из деструктора, похоже, экземпляр должным образом уничтожен , когда плагин отключен.Но когда я компилирую и запускаю в режиме выпуска , , деструктор никогда не вызывается, когда плагин отключен. Я не разработчик менеджера плагинов, не могу рассказать об этом слишком много.Большое спасибо за вашу помощь!

Вот фрагмент кода, который загрузил библиотеки плагинов.

newLib._libHandle = ::dlopen(path_to_the_plugin_lib, RTLD_LAZY | RTLD_GLOBAL);
if(! newLib._libHandle) {
  cerr << "dlopen failed for: " << path << " - "
             << ::dlerror();
  return "";

Я наконец-то заработал.Но до сих пор не понимаю, почему.Вот что я сделал:

class MySettings
{
   public:
      static MySettings& Instance() {
         return theSingleton;
      }

   private:
      static MySettings theSingleton;
      virtual ~MySettings();
}

MySettings MySettins:theSingleton;

Так как приложение очень большое с миллионами строк кода.Я сомневаюсь, что когда gcc компилируется в режиме RELEASE , что-то не так с оптимизацией.

1 Ответ

1 голос
/ 03 декабря 2011

Я никогда не пробовал это сам, документация , кажется, указывает, что статические переменные должны быть "повторно инициализированы" после перезагрузки.Для меня совершенно не очевидно, как это взаимодействует с пре-main() хуками C ++.Вы можете попытаться понять это (проверьте документацию вашего поставщика или просто откройте бинарный файл и посмотрите), но, вероятно, его проще перепроектировать.Некоторые идеи:

Если можете, избавьтесь от своих одиноких.Как уже упоминалось в комментариях, в наши дни консенсус в отрасли заключается в том, что в большинстве случаев синглтон-паттерн - это больше проблем, чем стоит - как вы обнаруживаете!Честно говоря, у вас не было бы этой проблемы в Java или Ruby, но все же.

Если вы компилируете с помощью gcc, вы можете зарегистрировать некоторые хуки для "до dlopen() возврата" и "после dlclose() называется ".Снова из документов:

...libraries should export routines using the __attribute__((constructor)) and __attribute__((destructor)) function attributes. See the gcc info pages for information on these. Constructor routines are executed before dlopen() returns, and destructor routines are executed before dlclose() returns."

Я почти уверен, что это зависит от gcc;если вы не используете gcc, ваша платформа может предложить нечто подобное.

Если вы не можете этого сделать, попробуйте переключиться на стиль «инициализация при первом использовании» одноэлементной реализации.Идея состоит в том, чтобы обнаружить в Instance(), был ли ваш MySettings синглтон уже создан, и сначала создать его, если это не так.Что-то вроде:

static MySettings* theSingleton = NULL;
if(theSingleton == NULL)
  theSingleton = new MySettings();
return *theSingleton;

Обратите внимание, что эта версия Instance() является не поточно-ориентированной;если вы хотите, вам придется пойти на некоторые неприятности.Также: theSingleton никогда не будет удалено, поэтому ваша проблема будет приводить к утечке памяти / файловых дескрипторов / чего угодно при каждой перезагрузке вашего плагина.В зависимости от того, что вы храните в MySettings и как часто вы ожидаете, что пользователи перезагрузят ваш плагин между перезапусками процесса, это может или не может быть приемлемым.

Надеюсь, это поможет.

...