Static and dynamic memory allocation of objects in C ++

In a C ++ program for a class, how can we get the number of active objects at any given time that are statically created and dynamically created separately?

+7
c ++
source share
5 answers

Sorry, you just can't. There is a whole section in one of Scott Meyer's books, where he talks about the problems associated with trying to achieve this, and if this is not so, it is impossible.

More efficient C ++ - Item # 27: Requiring or denying heap-based objects.

Well, here is one problem that is easy to demonstrate (this question takes several pages, so I won’t summarize it all, but there is at least one call here):

Many (but not all) systems organize their memory as follows:

---------------- | Stack | | (Grows Down) | | | ---------------- | | | | | | | | | | | | ---------------- | Heap | | (Grows Up) | | | ---------------- 

Now, you might think that with this memory configuration, you could do something smart with the new / new operator to find out if you are on the heap or wrong (checking if you are above or below a specific memory location)? Here is the problem. Where static objects go depends on the system, so the following may happen:

 ---------------- | Stack | | (Grows Down) | | | ---------------- | | | | | | | | | | | | ---------------- | Heap | | (Grows Up) | | | ---------------- | Static | | Objects | ---------------- 

Now you cannot distinguish between static and heap objects. Unfortunately! You may also have noticed that I said that it depends on the system, which means that even if you have to figure out a way to distinguish them, well, your code will not be portable.

+9
source share

Caveat: this uses "unedfined behavior" as described below - it is known to work on MOST platforms (I have enough understanding to say that it works on ARM and x86 on Windows, Linux and Symbian OS, and should be good for most OSs that use a "flat" memory model).

If you "limit" yourself to a particular system, you can compare this with the known range of "where is the stack" (and, if necessary), where is the static data). [One could figure out where the stack is for an arbitrary thread too, but this makes the task difficult].

Given where the static data and the stack are, we can compare

 char *this_addr = static_cast<char*>(this); if (this_addr >= globa_start && this_addr <= global_end) globals++; else if (this_addr >= stacK_top && this_addr >= stack_base) stacked++; else heaped++; 

Please note that this will only work if you can somehow determine where the stack is located, and, of course, the undefined behavior for comparing this with anything outside the block in which it was allocated, so technically , the concept is undefined. However, it is POSSIBLE to do this in most OS / Processor architectures. [Of course, you also need to do the same, but vice versa in the destructor]. (It also gets "pleasure" if you destroy an object from another thread, except the one that created it!)

Edit: Finding a stack for a given stream is not so difficult: save [to the stream, if there are several threads], the address of the local variable in the "first function" (the one that passed into the stream calls up). Then take the address of the variable in the current thread. Everything that is between these values ​​is on the thread stack, since the stack is one continuous piece of memory.

+2
source share

The easiest solution to track the number of active objects is to create an object manager (with the GetSize () function or something else)

In the class you want to track, you can also add a static property that will be increased and decreased in the constructors and destructors, respectively.

With the size of the object manager (dynamic allocation) and static property (all distributions), you can get these numbers separately.

0
source share

As an option, you can globally overload new ones and delete them to increase / decrease some static counter, which will give a global number of dynamically allocated objects ...

0
source share

You can simply tell the class by passing an argument about its location:

 class LocationAware { public: enum Location { STATIC, STACK, HEAP }; explicit LocationAware(Location location) : my_location(location) { switch(location) { case STATIC: ++static_instaces; break; case STACK: ++stack_instances; break; case HEAP: ++heap_instances; break; } } ~LocationAware() { switch(my_location) { case STATIC: --static_instaces; break; case STACK: --stack_instances; break; case HEAP: --heap_instances; break; } } private: const Location my_location; public: static unsigned static_instaces; static unsigned heap_instances; static unsigned stack_instances; }; unsigned LocationAware::static_instaces = 0; unsigned LocationAware::heap_instances = 0; unsigned LocationAware::stack_instances = 0; LocationAware stat(LocationAware::STATIC); int main() { LocationAware stack(LocationAware::STACK); LocationAware * heap = new LocationAware(LocationAware::HEAP); } 

Of course you can lie to this class. Do not do this.

Also, if you want to make it less intrusive, you can make it a template and use inheritance or encapsulation and use it from your class. Just give it a parameter:

 template<class Tag> LocationAware; 

Then either inherit or hold a place in your class and initialize it. You can see instances using LocationAware<YourClassOrTag>::xy_instances .

0
source share

All Articles