@CPPJunior

Почему обнуляется статический член класса?

Здравствуйте!
Возникла проблема со статическим членом класса. Имеется класс-счётчик:

// counter.h
class counter
{
   friend class Manager;
public:
   typedef boost::shared_ptr<counter> s_ptr;
   typedef boost::weak_ptr<counter> w_ptr;

   inline static s_ptr create()
   {
      return s_ptr(new counter());
   }

   inline static void set_current(s_ptr p_counter)
   {
      current_ = p_counter;
   }

private:
   counter():lastId_(0) {}

   //return new value
   int inc() {return ++lastId_;}

   int lastID() {return lastId_;}

   inline static s_ptr current()
   {
      return s_ptr(current_, boost::detail::sp_nothrow_tag());
   }

private:
   int lastId_;
   static w_ptr current_;
};

// factory.cpp
counter::s_ptr counter::current_; // объявляем статический член

Как мы видим из кода, это действительно просто счётчик. В нём есть статический член - слабый указатель на объект этого же класса. Статический член является заменой глобальному счётчику. Но он произвольно обнуляется (т.е. именно ссылка нулевая 0x0000000). Вот пример использования:

// manager.cpp
void Manager::addRecord(int row, int id, Record* parent)
{
   // manager устанавливает свой счётчик. Тут counter::current_ определён
   counter::set_current(counter_); 
   // внутри этого метода должен действовать счётчик менеджера, но он обнуляется.
   parent->insertRecord(row, id); 
}


// Record.cpp
void Record::insertRecord(int row, int id)
{
   counter cntr = counter::current(); // 0x0000000
   // попытка использования влечёт access violation
}


Все вышеупомянутые классы (и соответствующие файлы) находятся в одном проекте. Когда я пытаюсь с помощью дебагера отследить адрес памяти, по которому находится counter_ я вижу, что как будто бы сам счётчик не пропадает (т.е. он существует и память не освобождается). Обнуляется именно статический член. При этом ни конструктор ни set-метод класса counter не срабатывают.
Подскажите пожалуйста в чем может быть дело?

P.S.: приложение однопоточное.
P.P.S.: IDE = visual studio 2008
  • Вопрос задан
  • 2362 просмотра
Пригласить эксперта
Ответы на вопрос 2
@Koss1024
weak_ptr не владеет объектом
объект указателя будет уничтожен кем-то из вне. А именно когда все shared_ptr объекты будут уничтожены

На самом деле код весьма запутан.
Из за того что у вас есть friend не возможно ничего сказать о безопасности приватных конструкций
Без кода класса менеджера вообще ничего не понятно.

Скорее всего вы сами его и обнуляете в менеджере не созданным объектом.

Совет: используйте SRP не объединяйте сущности
Counter должен считать и не следить за тем кто теперь текущий
A какой нибудь CurrentCounter - статический член, глобальная переменная или синглтон - отдельный объект

и проблем не будет

----

Все же я дополню

такой код всегда получается из-за чрезмерного увлечения паттернами, без понимания зачем они нужны.
сформулируйте лучше задачу свою поточнее, мы вам поможем с архитектурой.

Что вы хотите от этого счетчика? Зачем он нужен? Зачем переключать глобальный текущий?
Какую задачу он решает?

Я серьезно. Вопросы архитектуры очень важны.
Ответ написан
@xandox
поробуй вместо
inline static s_ptr current()
   {
      return s_ptr(current_, boost::detail::sp_nothrow_tag());
   }

вот это
inline static s_ptr current()
   {
      return current_.lock();
   }

а когда это сломается, прочитай первый ответ.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы