1

How can I instrument C++ code such that I can get the object count per class at runtime?

I could overload the new and delete operators, implement custom constructors/destructors, but I am looking for a generic approach that does not require altering all classes in my code.

Lemon Sky
  • 677
  • 4
  • 10
  • 1
    Check this out https://stackoverflow.com/questions/1926605/how-to-count-the-number-of-objects-created-in-c – ThivinAnandh May 04 '21 at 19:48
  • Please update the question to clarify whether you want to count one (or a small number of classes) or all classes including those not under your control such as `std::string`. The first case is easy and covered by the posted answers and comments. The second case... Ouch. – user4581301 May 04 '21 at 20:00
  • The base class is not bad, but I'm looking for a generic approach. Whether std::string is included or not - basically at this point, I'll take what I can get. I'm happy if I can get statistics for all classes in my own git repository. – Lemon Sky May 04 '21 at 20:31

4 Answers4

2

One way is to have a static count member on the class. You would have to increment it each time a constructor is called, and decrement when destructor is called.

E.g.

class SomeClass {
  private:
    static uint64_t count;

  public:
    SomeClass() {
        ++count;
    }
    ~SomeClass() {
        --count;
    }
};

// Initialize count
uint64_t SomeClass::count = 0;
Zois Tasoulas
  • 1,242
  • 1
  • 11
  • 23
  • 1
    Modern C++ allows `static inline` class member variables to be initialized in the class declaration. – Casey May 04 '21 at 20:12
  • Thanks but this would not be "tools or ways to instrument C++ code". Of course I can count objects if I manually code something into every class. (On top of that, I believe this solution is not thread-safe) – Lemon Sky May 04 '21 at 20:36
1

I don't think there is a direct way to record the number of created objects without modifying the class as suggested by the other answers. There are however tools that can count the number of function invocations, so we can infer the number of objects from the number of constructor or destructor calls. Destructors are probably easier to count because they don't have overloads.

Tools that can do that include callgrind (part of the valgrind suite). Source-level instrumenters like gprof, TAU or Score-P would also be an option.

Probably only works if the class you're interested in actually defines a destructor/constructor though.

dabo42
  • 486
  • 3
  • 6
  • This sounds like the most promising answer, can you be more concrete though? My concern is, if I'm too low level, will I even get the class name to make a sensible statistics for humans to look at? – Lemon Sky May 04 '21 at 20:33
  • With all of the tools you get class names and calling context (i.e., where you called what function). In fact, if you use callgrind you'll have to postprocess the output to sum up the total number of calls in all different locations. Maybe the KCachegrind GUI can do that. An easier option might be gprof, but like TAU and Score-P it requires recompilation. – dabo42 May 04 '21 at 21:00
0

The easiest is to have a static member that counts the number of instances. The constructors need to increment them, and the destructor will decrement it. To access it, you will need a public static getter.

class C
{
   private:
      static size_t c;
   public:
      C() { c++; }
      C( const C& other )
      {
        c++;
        *this = other;
      }
      ~C() { c--; }    
      static size_t getNb()
      {
        return c;
      }

};

// counter instanciation
size_t C::c = 0;

This could possibly be templated, but it has limitations, as you can't have specific constructors/destructors. See linked answer for a more generic approach.

kebs
  • 6,387
  • 4
  • 41
  • 70
  • Once you declare the copy constructor the default assignment operator [may not be auto-generated for you](https://en.cppreference.com/w/cpp/language/copy_assignment#Implicitly-defined_copy_assignment_operator). I do not believe this has been formally removed from the language as of C++20, but it's removal will come eventually. – user4581301 May 04 '21 at 20:05
  • @user4581301 thanks, corrected the const. indeed, seems to be fine without a user-defined assignment operator, I just checked, see http://coliru.stacked-crooked.com/a/9211f2f7f3fac3b2 – kebs May 04 '21 at 20:11
  • 1
    I was getting ahead of myself there. Behaviour I described is deprecated, but not yet formally removed. – user4581301 May 04 '21 at 20:12
  • I find the answers here quite similar, from my C# perspective, that is. Q: This extra constructor that takes an instance of C why is that needed ? if you would use this as a "counter class" for other classes that derive from it, this constructor C(&..) can't be used (?) – Goodies May 04 '21 at 20:17
  • Thanks but this would not be "tools or ways to instrument C++ code". Of course I can count objects if I manually code something into every class. (On top of that, I believe this solution is not thread-safe) – Lemon Sky May 04 '21 at 20:38
  • 1
    @Goodies `C( const C& other )` is a copy constructor. It's there to make sure that is you make a new `C` by copying an existing `C` it will also be counted. Why would you want to make a copy? Happens all the time in C++. For example, if you pass an object by value, it'll be copied. In practice the compiler will do everything in its power to eliminate actually making the copy, but if you ask for a copy and making that copy has a side effect like incrementing a counter, that counter must be incremented. – user4581301 May 04 '21 at 21:23
  • One notable exception is [copy elision](https://en.cppreference.com/w/cpp/language/copy_elision) where the side effects are allowed to be ignored. – user4581301 May 04 '21 at 21:23
  • @LemonSky That requirement ("not require altering all classes in my code") seems to have been introduced after I entered my answer... And, sure, not thread safe... but you didn't ask for that either. – kebs May 05 '21 at 21:13
  • Yes, I had "generic solution" along with "instrumentation" and "tool", and the goal I had in mind was that "I don't have to do a lot of repetitive work". This wasn't clear from reading the answers, so I corrected the question. – Lemon Sky May 06 '21 at 18:57
  • Didn't ask for thread safety but I need a solution that works in all the weird and wonderful ways software is written today. – Lemon Sky May 06 '21 at 18:58
0

Instead of overloading you could try defining a macro which redefines all the new keywords in the entire project.

#define new (some code to create and log)
Richard Nagy
  • 141
  • 9