C
C
CPPJunior2014-12-01 10:11:57
C++ / C#
CPPJunior, 2014-12-01 10:11:57

Why is a static class member nullified?

Hello!
There was a problem with a static class member. There is a counter class:

// 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_; // объявляем статический член

As we can see from the code, this is really just a counter. It has a static member - a weak pointer to an object of the same class. The static member is a replacement for the global counter. But it is arbitrarily reset to zero (i.e. exactly the reference is null 0x0000000). Here is an example of usage:
// 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
}

All of the above classes (and their respective files) are in the same project. When I try to track the memory address where counter_ is located using the debugger, I see that the counter itself does not seem to disappear (that is, it exists and the memory is not freed). It is the static member that is reset. In this case, neither the constructor nor the set-method of the counter class work.
Please tell me what could be the matter?
PS: The application is single-threaded.
PPS: IDE = visual studio 2008

Answer the question

In order to leave comments, you need to log in

2 answer(s)
K
Koss1024, 2014-12-01
@Koss1024

weak_ptr does not own the object
, the pointer object will be destroyed by someone outside. Namely, when all shared_ptr objects will be destroyed
. In fact, the code is quite confusing.
Due to the fact that you have a friend, it is not possible to say anything about the safety of private constructions
Without the code of the manager class, nothing is clear at all.
Most likely, you yourself reset it in the manager with an uncreated object.
Tip: use SRP do not merge entities
Counter should count and not keep track of who is now the current
A some kind of CurrentCounter - a static member, a global variable or a singleton - a separate object
and there will be no problems
----
Still, I will add
such code is always obtained due to excessive enthusiasm for patterns, without understanding why they are needed.
better formulate your task more precisely, we will help you with the architecture.
What do you want from this counter? Why is it needed? Why switch global current?
What problem does he solve?
I'm serious. Architectural issues are very important.

X
xandox, 2014-12-01
@xandox

try instead

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

this
inline static s_ptr current()
   {
      return current_.lock();
   }

and when it breaks, read the first answer.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question