Class-specific new and delete called inconsistently

时间:2017-08-30 20:22:00

标签: c++ new-operator delete-operator

I'm working on implementing memory pools for my project. The idea is to have any class which inherits from MemoryPoolObject automatically use the memory pools when allocated using new/delete. The problem is that my overridden new and delete operators are only being called about half the time. I suspected this early on, so I confirmed this by counting the number of times that the MemoryPoolObject constructor and destructor get called, and comparing that to the number of times that the overloaded new/delete are called.

Here's what the class looks like:

.navbar>.container .navbar-brand, .navbar>.container-fluid .navbar-brand {
    float: none; /* This is for the .container-fluid height to match the image height, and therefore allow for a possible bottom alignment of its ul sibling */
}

#mainNavBar {
    float: none;
    vertical-align: bottom;
}
#mainNavBar > li {
    float: none;
    display: inline-block;
    vertical-align: bottom;
}

Here are the usage stats for the project's unit tests when I make the base class for most of my classes inherit from MemoryPoolObject:

B   +--------------------+
I   |Row1 Row1 Row1 Row1 |
G   |     Row2      Row2 |
    |     Row3           |
I   |                    |
M   |                    |
A   |                    |
G   |                    |
E   +--------------------+

As you can see, I'm getting about twice as many calls to the constructor/destructor as I am to the overloaded new/delete operators.

It's also worth mentioning that very nearly all of the allocation is done from the same place:

B   +-------------------+
I   |                   |
G   |                   |
    |                   |
I   |                   |
M   |     Row1          |
A   |     Row2      Row1|
G   |Row1 Row3 Row1 Row2|
E   +-------------------+

By setting a flag inside of allocate() and then checking it in objectConstructed() I was able to catch the place where the problem was happening - and I confirm that calls from here sometimes call the class's new operator and sometimes do not.

To address some of the comments...

There is no placement new in the library at this time. There are a few cases where objects are created on the stack, but as I said in the previous paragraph, I've been able to confirm it happening from a plain old new. Also, everything created on the stack is going to have its destructor called - there aren't nearly enough destructor calls. Also, I've been able to set breakpoints and catch my delete operator not being used from a regular delete call.

This is being used for a large modular AI library (here's an article on modular AI: https://www.msco.mil/DocumentLibrary/Journals/MSJournalFall2013.pdf). It's hard to show all the detail because there's a lot going on. However, the basic idea is that you have a bunch of interfaces defining broad types of objects - nodes, considerations, utility values, etc. Each of these interfaces may have many children, which are constructed using factories. The factories are templated, and call into the instantiate function that I show above.

A typical class structures goes something like this. The root class is MemoryPoolObject. LoadableObject (which includes the instantiate function) inherits from that. ComponentBase inherits from LoadableObject. The interface class (NodeBase, ComponentBase, etc.) inherits from ComponentBase. The concrete classes inherit from the interface classes. There are some exceptions that inherit directly from LoadableObject... but this problem persists whether I make MemoryPoolObject a base class for LoadableObject or a multiply-inherited base class for ComponentBase.

Interestingly, there is some indication (possibly false - I'm still debugging) that this might be a cross-project problem. The unit tests exist in one project, and they load the AI project as a static library. I'm wondering it the problem is that objects that belong to the unit test project don't call the class-specific new and delete in the AI project, even though they inherit from MemoryPoolObject. Those objects are also in a different namespace - but I don't see why either of those things should be relevant (at least, in theory).

I may try using a different compiler, and see if that changes the outcome.

0 个答案:

没有答案