Using malloc() with C++ Objects...possible?

Started by
4 comments, last by codemonkey 23 years, 9 months ago
Ok, this is going to sound wierd, but I want to use malloc() to allocate a new object in C++. I understand that normally the "new" operator is used, however I am writing a memory reporting tool over the malloc() operator and would like to know if there was a way to work this. The only idea I had so far is perhaps overloading the global ::new() routine so when I "new" and object it runs my code. Here is what I would like to do: CObject *Obj; Obj = (CObject *)malloc(sizeof(CObject)); And this works fine (memory space wise), and is good for structures. _However_ it does not call my default constructor for me. So what I would really like is: 1. Be able to get the same functionality from malloc as I do from new (meaning, I would like it to call the default constructor). -or- 2. Be able to overload the new operator transparently so that I could call it as needed, and run my memory reporting code. -or- 3. To be able to call the default constructor explicitily after malloc''ing my data block. Any ideas? Thanks, Derrick PS: As for free() I would like to be able to do the same as new, but call the destructor instead.
CODE Monkey
Advertisement
I think you can overload operator new just like you can overload any other operator... But I''m not totally sure.
I''ve overloaded the new operator before - there are a couple of things you must do:

1. The return type must be void* (the compiler handles the type-checking directly), which is a pointer to the newly allocated memory.
2. The first parameter must be a size_t, and it always indicates the size of the memory to be allocated.

Inside the new operator, you declare a void*, call malloc with with size_t as the parameter, and then do whatever else you''d like to do (reference counting, etc.). You can add parameters to the new operator if you like, but the first one must be a size_t, and the compiler always fills in that value for you.

If we overload the new operator like this:


void* operator new(size_t bytes, int ID)
{
void* p = malloc(bytes);

// do something with ID

return p;
}



Then you call that overloaded new operator like this:


int* p = new(1) int;



1 is passed to new as the second parameter, which is ''int ID''. Again, you can add whatever parameters you like, and new looks kind of like a function call. (Actually, this might be a good way of hiding a class factory ). I''m not sure how the new operator for arrays is overloaded. You can probably overload delete in the same way as you overload new, except that I don''t think that delete needs to know the size.

BTW, you don''t have to call constructors or destructors yourself - the compiler does that for you after new returns and before delete is called.



- null_pointer
Sabre Multimedia
This is happy news! I got it working, but I didn''t even need the "int ID".

I was able to overload the normal operator:

void *operator new( size_t size)
{
// Code monkey''s own MALLOC routine
void *p = MALLOC(size);
return p;
}

However, I a have a few other issues. I am building a memory management routine for debugging that will allow me to trace all of the memory being used by my application. So I have something like so (this is from memory, I don''t have the code in front of me right now)

#define MALLOC(size) blmalloc(size, __FILE__, __LINE__)

And my "blmalloc()" routine logs the file and line the MALLOC() was called on. So I need to be able to pass the __FILE__ and __LINE__ directives to new. So I could do something like

new(__FILE__, __LINE__) size;

Which works fine, but when I write its counterpart (delete) and call something like:

delete(__FILE__, __LINE__) pClassPointer;

I get a compiler error stating I am missing a semi-colon before pClassPointer. That usually means some syntax error is causing me grief. Do you know by chance if I am formatting the delete call wrong? The MSDN shows a very simple delete routine that takes no extra parameters.

Anyway, you''ve been a great help and I am sure I can suffer through this and figure it out over the course of a few days if you can''t give me an answer.

Thanks,

CodeMonkey
CODE Monkey
I wrote this for tracking down memory leaks...perhaps it could be to some use for you. (Not all the source is included)

    #if defined(_DEBUG) && CL_DBG_TRACKMEMORYLEAKS#	include <malloc.h>	void clRemoveAllocRecord(unsigned long addr);	void clAddAllocRecord(unsigned long addr, size_t size, const char* filename, int line);	inline void* __cdecl operator new(size_t size, const char* file, int line)	{		void* p = malloc(size);		clAddAllocRecord((unsigned long)p, size, file, line);		return p;	}	inline void* __cdecl operator new[](size_t size, const char* file, int line)	{		void* p = malloc(size);		clAddAllocRecord((unsigned long)p, size, file, line);		return p;	}	inline void __cdecl operator delete(void* p)	{		clRemoveAllocRecord((unsigned long)p);		free(p);	}	inline void __cdecl operator delete[](void* p)	{		clRemoveAllocRecord((unsigned long)p); free(p);	}#	define DEBUG_NEW new(__FILE__, __LINE__)#else#	define DEBUG_NEW new#endif#define new DEBUG_NEW#if defined(_DEBUG) && CL_DBG_TRACKMEMORYLEAKS	bool clDumpMemoryLeaks(const char* filename);	bool clMemoryLeaksFound();#else#	define clDumpMemoryLeaks(x)	false#	define clMemoryLeaksFound() false#endif    


Now, you''ll have the line and file for each allocation issued by new! Not the de-allocations however but you can tweak it so you get them too. Just as easy as eating pancakes. This way is very similar to how MFC does it. I''ve found one quirk using this, you have to include the file containing the code above _after_ any includes of the STL files (in MSVC6 that is...don''t know about others). I hope that helps.

"Paranoia is the belief in a hidden order behind the visible." - Anonymous
Sometimes I just don''t get time online...sorry for not answering right away.

VC doesn''t fully support the STL new operators either, so it''s probably some compatibility thing.

Hmm...I finally got it to work. Here''s the working code, although the syntax is clunky:


// test31.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include

inline void* operator new(size_t bytes, const char* file, const unsigned int line)
{
return malloc(bytes);
}

inline void operator delete(void* data, const char* file, const unsigned int line)
{
free(data);
}

#define new new(__FILE__, __LINE__)
#define delete(p) operator delete(p, __FILE__, __LINE__)

int main(int argc, char* argv[])
{
int* p = new int;
delete(p);
return 0;
}



There are two things you have to remember: 1) you have to call delete using the parentheses (although you can use a variable name more descriptive than ''p''), and 2) you can''t use the parentheses with new. However, the file and line numbers will be transfered correctly!

You can also override the array operators if you want to track all allocations. I''m not sure if the same trick of using the parentheses will work when overriding the delete[] operator, though.

Happy Coding!


- null_pointer
Sabre Multimedia

This topic is closed to new replies.

Advertisement