Let's imagine that we have a big project. In which there are many classes, objects of these classes, containers of objects, and so on.
Can I view the dimensions of all these objects? Output, for example, a table or a list of all objects, containers, with their sizes.
Of course, for a project, for example, in 20000 lines, I will not be able to display everything by hand.
It is important that this can be done not only after the completion of the program, but during execution Are there any utilities, programs, perhaps this can be done using gdb or some other means.
I hope I explained the question exhaustively, ask questions, I will explain what I can.
CodePudding user response:
As Neil Butterworth pointed out, C does not maintain a list of objects by itself, but if you really wanted to, you could implement it yourself: Create a class that tracks its instances and have all classes whose instances you want to monitor inherit from it. However, you’re probably better off using conventional debugging tools (example) to get the information that you need. Maybe there is a better whay to diagnose your problem than to print a list of all objects and their sizes – see the XY problem.
If you really want to try the instance list approach, here’s some code:
ListedObject.h
#include <unordered_set>
#include <string>
#include <cstdio>
class ListedObject
{
private:
static std::unordered_set<const ListedObject*> objectList;
public:
ListedObject ()
{
objectList.insert(this);
}
virtual ~ListedObject ()
{
objectList.erase(this);
}
virtual std::size_t loSize () const = 0;
// You will need to override this with e.g.
// std::size_t loSize () const override {return size();}
virtual std::string loName () const
{
return "<anonymous>";
}
// You need a mechanism to give the objects names that exist at runtime
// (your variable names won’t)
static void printObjects ()
{
for (const ListedObject *const lo : objectList)
{
std::printf("%s %zu\n", lo->loName().c_str(), lo->loSize());
}
}
};
ListedObject.c
#include "ListedObject.h "
std::unordered_set<const ListedObject*> ListedObject::objectList;
You would use it like this:
#include "ListedObject.h "
class DummyContainer: public ListedObject
// not really a container, just something that simulates having a size
{
public:
std::size_t dummySize;
DummyContainer (std::size_t dummySize): dummySize(dummySize) {}
std::size_t loSize () const override
{
return dummySize;
}
};
int main (void)
{
DummyContainer d1(4);
DummyContainer d2(12);
{
DummyContainer d3(1337);
}
DummyContainer d4(42);
ListedObject::printObjects();
// For me, this prints:
// <anonymous> 42
// <anonymous> 12
// <anonymous> 4
return 0;
}
However, this approach won’t work for classes you can’t edit, like std::vector
s. You could try to get around this with something like…
template <class T>
class ListedVector: public std::vector<T>, public ListedObject
{
public:
std::size_t loSize () const override
{
return sizeof(T) *
//size(); // does not compile for some reason¹
static_cast<const std::vector<T>*>(this)->size();
}
};
…, but this will not inherit the various constructor signatures of std::vector
s.
¹ gcc says: “error: there are no arguments to ‘size’ that depend on a template parameter, so a declaration of ‘size’ must be available [-fpermissive]”
CodePudding user response:
Output, for example, a table or a list of all objects, containers, with their sizes. Of course, for a project, for example, in 20000 lines, I will not be able to display everything by hand.
Yes, you can do that. Either by writing appropriate object-tracking code and linking it into your program, or by writing a GDB script to enumerate objects "externally".
However, usually this request means that you want to understand your program via debugger instead of understanding it by reading the code. And the former task is usually about 10 times harder than the latter.
In addition, 20,000 line program is relatively small. A big project is something with a few million lines of code.