PDA

View Full Version : Tracking memory consumption of plugins.



spud
28th August 2007, 15:11
I've written an application which supports plugins. Now I am wondering: which is the easiest way(from the perspective of the plugin programmer) to track how much heap memory a plugin has reserved, so that it can be displayed in the main application.

The restrictions I am currently imposing on the plugin programmer are:
They must inherit an interface that looks like:


class plugin
{
void init();
void process();
void reset();
};

They aren't allowed to keep member or stack variables, but should allocate memory in init() and release in reset().
They must include a certain header file of mine.


Now, the perfect solution would be completely transparent and impose no further restrictions on the programmer. I was hoping I could overload the new operator for the plugin class:


class plugin
{
...
void *operator new( size_t n);
void operator delete( void *p, size_t n);
void *operator new[]( size_t n );
void operator delete[]( void *p, size_t n);
};
but that isn't enough if the constructors of the objects created also call new. I could catch some cases by reimplementing the global new the same way:


void *operator new( size_t n);
void operator delete( void *p, size_t n);
void *operator new[]( size_t n );
void operator delete[]( void *p, size_t n);

and I guess I should do the same with malloc and free for good measure.
But what if the plugin programmer uses classes defined in a dynamic library. Is there a way to "insert" my new operator into other libraries?

I am not looking for a perfect solution that tracks everything. Typically an init() function will reserve a couple of images and lookup maps, etc.

Here is an example:


void init()
{
// Handled by my global new operator:
lum = new unsigned char[256][256][256];

// OK, as long as they use my image class for which I can reimplement new
img = new Image(800,600, rgb, s8bit);

// What about the stl, it relies heavily on placement new, will my new get called?
// And it seems most classes has an "allocator" template argument.
// The following seems to work, but is that always the case?
data = new std::vector<int>;
data->resize(128*128);
}


There must be other ways as well, but it seems they all mean more restrictions(or tedious work) for the plugin programmer.

I'm thankful for any ideas how to go about this.

fullmetalcoder
28th August 2007, 18:37
The restrictions I am currently imposing on the plugin programmer are:
They must inherit an interface that looks like:
They aren't allowed to keep member or stack variables, but should allocate memory in init() and release in reset().
They must include a certain header file of mine.

This does not look like an interface to me... I assume it only "looks" like it then... You wouldn't get far otherwise...;)
I'm just wondering how you expect the plugins not to use stack... All local variables make use of stack and you'll need some, even if you allocated a big bunch of data where you'd store the actual variables (which, besides bringing a lot of complexity, would be an incredible waste of memory and time IMO)
Well, that's a restriction common to ANY plugin due to there very nature...:p

spud
28th August 2007, 19:33
1. Yes I have simplified things a bit:p
2. I guess I could have been clearer on that point. There is no way for me and I have no intention to stop anybody from using the stack. I'm not worried about that because it won't accumulate or add up to much anyway. What I do worry about is adding images and lookup maps etc as data members. The allocation of these shouldn't happen in the constructor, but in the init() function where I can control it.
3. Yes that is a common but necessary restriction. What I want to avoid is forcing the programmer to write code like:


void init()
{
img = new Image(800,600, rgb, s8bit);
iJustAllocated(800*600*nrOfChannels(rgb)*sizeof(s8 bit));
}
void release()
{
delete img;
iJustFreed(800*600*nrOfChannels(rgb)*sizeof(s8bit) );
}

So if you have any suggestion how I should do that...:cool:

wysota
7th September 2007, 13:14
You can have a stack variable with a small memory footprint that will simply be initialized in the init, like so:

class .. {

private:
QImage img;
...};
void ...::init(){
img = QImage(800,600,...);
}
img is allocated on stack but initialized (and expanded) in init().

BTW. In the interface those methods have to be virtual.