Click to See Complete Forum and Search --> : overwriting new and delete
seany
April 5th, 2006, 05:53 AM
Hi all,
I am overriding new and delete for some c++ classes.
I am wondering if its also ok to override new and delete in the same way for structures.
i.e. when declaring a struct, redefine the operator new and delete for that struct
or
Is it only possible to override new and delete that structures will end up using by overriding global new and delete.
Cheers,
Seany.
DragForce
April 5th, 2006, 08:21 AM
struct is almost equivalent to class. So overwriting operator new for a struct will give the same effect as overwriting one for a class.
MrViggy
April 5th, 2006, 10:54 AM
IIRC, in C++ a struct is the same as a class, with all members 'public' by default. As a matter of fact:
#include <iostream>
struct SomeStruct
{
SomeStruct() : m_AnInt(0) {}
int GetMe() { return m_AnInt; }
void ModMe() { UpdateMe(); }
private:
void UpdateMe() { ++m_AnInt; }
int m_AnInt;
};
int main(/*int argc, char *argv[]*/)
{
SomeStruct testStruct;
std::cout << "My test is currently: " << testStruct.GetMe() << std::endl;
testStruct.ModMe();
testStruct.ModMe();
testStruct.ModMe();
std::cout << "My test is now: " << testStruct.GetMe() << std::endl;
return 0;
}
Should output:
My test is currently: 0
My test is now: 3
But, if I try to access 'UpdateMe' directly, I get:
d:\Projects\JunkConsole\test.cpp(23) : error C2248: 'SomeStruct::UpdateMe' : cannot access private member declared in class 'SomeStruct'
Viggy
NMTop40
April 5th, 2006, 11:11 AM
inheritance is also by default private for a class and public for a struct.
This can be quite confusing but I'm pretty sure it's this way round:
struct A{};
class B : A{}; // private
struct C : B{}; // public
DragForce
April 5th, 2006, 11:30 AM
IIRC, in C++ a struct is the same as a class, with all members 'public' by default.
Don't you contradict yourself?
SuperKoko
April 5th, 2006, 11:42 AM
Don't you contradict yourself?
It is a syntactic difference. Only the default access rights to members.
Everything is exactly the same...
So, a struct is a class and a class is a struct.
But a class definition is not exactly (but very similar) the same than a struct definition.
Vedam Shashank
April 6th, 2006, 12:55 AM
But a class definition is not exactly (but very similar) the same than a struct definition.
Did not folllow this ??
SuperKoko
April 6th, 2006, 04:51 AM
Did not folllow this ??
A class is a struct and a struct is a class:
struct TObject; // declaration
class TObject // definition
{
int x; // here, x is private
};
int main()
{
struct TObject x;
class TObject y;
}
That code should work.
However, using the struct-keyword instead of the class-keyword is a bit different when defining a class:
struct TObject; // declaration
struct TObject // definition
{
int x; // here x is public
};
int main()
{
struct TObject x;
class TObject y;
}
seany
April 6th, 2006, 06:56 AM
Jeez guys!
Ye were havin fun. My post has turned from operator overloading to misunderstandings in textual descriptions between classes and structs.
Thanks for the posts anyway, it made me laugh!
Dragforce confirmed what I was looking for in the first post.
It just means I have a problem. I have defined new and delete in my struct to override the allocation mechanism and when I debug into it, my definition of operator new gets called but when I delete my struct the system delete gets called. This is a problem.
i.e.
struct test
{
void* operator new( size_t sz )
{
....
}
void operator delete( void* ptr )
{
.....
}
cList<int> m_nodes;
cList<float> m_values;
};
How I use it
test* a = new test;
....
delete test;
Are there situations where my overload of operator new would be called but when delete is called it calls the system delete. Does it not recognize the definition. Note: Code compiles and runs without error.
exterminator
April 6th, 2006, 08:39 AM
I suspect the void pointer to your overloaded delete operator:
void operator delete( void* ptr )
This could also be disastrous depending upon what is done in the inside. You should not call delete on a void* - delete (or overloaded delete) must be called on the same type whose allocation was done with new (or overloaded new). Hope this helps.
By the way, why do you need to specialize these operators for your class and structs? Regards.
SuperKoko
April 6th, 2006, 09:03 AM
I suspect the void pointer to your overloaded delete operator:
void* is the correct parameter!
operator delete frees raw memory.
SuperKoko
April 6th, 2006, 09:09 AM
seany : try that code:
#include <cstdlib>
#include <iostream>
struct test
{
void* operator new( size_t sz )
{
std::cout << "[new "<<sz<<"]";
return std::malloc(sz);
}
void operator delete( void* ptr )
{
std::cout << "[delete @" << ptr << "]";
std::free(ptr);
}
};
int main()
{
test* p=new test;
delete p;
}
It works as expected with GCC (assuming malloc doesn't fail), and should work with your compiler.
If your compiler is buggy on that code, then, try to add a second size_t parameter to operator delete.
void operator delete( void* ptr , std::size_t)
{
std::cout << "[delete @" << ptr << "]";
std::free(ptr);
}
Also, in order to be more explicit for human people, and perhaps for the compiler if it is not ISO compliant, I suggest you explicit the static keyword for these operators:
#include <cstdlib>
#include <iostream>
struct test
{
static void* operator new( size_t sz )
{
std::cout << "[new "<<sz<<"]";
return std::malloc(sz);
}
static void operator delete( void* ptr, std::size_t )
{
std::cout << "[delete @" << ptr << "]";
std::free(ptr);
}
};
int main()
{
test* p=new test;
delete p;
}
seany
April 6th, 2006, 09:39 AM
Guys,
This is not a problem with my code but with an external library........
Guess what it is......
ATL
ATL overrides new and delete also.
ATL has a different definition of operator new to the standard new operator and delete is the same definition in ATL as the standard library delete.
So......the code is allocating fine using my new operator as it matches the parameter list I pass in. The delete however is the same as the ATL definition, so when I delete anything, the bloody ATL delete operator gets used.
Without changing the definition of my operators, is there any way to get ATL to turn off its operator overloading. ATL is needed, I just want none of its memory support.
A question above, asked why I override the new and delete.
New and delete can be overridden when you wish to use your own memory allocator or if you need to perform analysis on the memory use of your program, so you can attach debug to allocations etc.
There is no rule in C++ which states do not use it, you just need to know how to use it properly. Unfortunately, some other libraries like the same idea.
SuperKoko
April 6th, 2006, 10:06 AM
ATL has a different definition of operator new to the standard new operator and delete is the same definition in ATL as the standard library delete.
ATL uses a custom operator new, but uses the standard delete? :confused:
Your problem may be due to the fact that you inherit from a class having no virtual destructor, but an overloaded operator delete, and you delete a derived class via a base class pointer.
Anyway, behaviour is undefined : With or without operator overloading.
If you derive from a class having no virtual destructor, you can define a virtual destructor into your derived class, and use this class as a root for all your class hierarchy, and then, you'll delete all your objects via a pointer to your root class, which is correct!
Note : If the destructor is virtual, the correct operator delete will be called.
operator delete, if the destructor is virtual, can be seen as a static virtual function invoked after the death of the class.
In the worst case, your new "root class" will be trivial:
class MyRootClass: public TheClassWhichHasNoVirtualDestructor
{
public:
virtual ~MyRootClass() {}
// nothing more here
};
exterminator
April 6th, 2006, 10:17 AM
SuperKoko, thanks for correcting me.
Seany - basically the type being used with the delete expression should determine which delete is to be called. If the correct one is not being called you can try explicitly calling the corresponding delete for the used new expression. But before that can be done, can you please post the version of new and delete that you are having problem with?
For the array form of operator delete - even when the destructor is defined virtual - the behaviour is undefined if the static type of the object and dynamic type are different (i.e. in a hierarchy). From the standards:struct B {
virtual ~B();
void operator delete[](void*, size_t);
};
struct D : B {
void operator delete[](void*, size_t);
};
void f(int i)
{
D* dp = new D[i];
delete [] dp; // uses D::operator delete[](void*, size_t)
B* bp = new D[i];
delete[] bp; // undefined behavior
}
seany
April 6th, 2006, 10:54 AM
I am using a simple struct guys, no classes, no inheritance.
A simple struct and it uses my new operator but the ATL delete
because the ATL delete operator matches the parameter
definition of my delete.
exterminator
April 6th, 2006, 11:02 AM
Please show the ATL overload and your specific overload. I think you need to call the operator delete with explicit syntax with the arguments.
seany
April 6th, 2006, 11:12 AM
my delete:
inline void operator delete(void* ptr)
{
free( ptr );
..
}
ATL definition my code is using:
void __cdecl operator delete(void* p)
{
#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
_free_dbg(p, _NORMAL_BLOCK);
#else
free(p);
#endif
}
SuperKoko
April 6th, 2006, 11:14 AM
because the ATL delete operator matches the parameter
definition of my delete.
:eek:
You know, operator delete has class scope.
Which means that:
struct S1
{
void* operator new(size_t); // It declares S1::operator new
void operator delete(void*); // It declares S1::operator delete
};
struct S2
{
void* operator new(size_t); // It declares S2::operator new
void operator delete(void*); // It declares S2::operator delete
};
S1::operator delete has no conflict with S2::operator delete !
Please, show your code.
exterminator
April 6th, 2006, 11:19 AM
I am not sure and the class scope definition should have had been used but still try doing something like this:MyClass::operator delete (p);
MyClass is the class for which the operator is overloaded. Again, I am not sure if this works or is a correct syntax but Comeau didn't have any problems. Regards.
seany
April 6th, 2006, 11:49 AM
The implementation I have uses a macro such as when I declare a struct I do it like:
struct someObject
{
inline void* operator new(size_t sz){ ... } calls malloc
inline void operator delete(void* ptr){ ... } calls free
inline void* operator new[](size_t sz){ ... } calls malloc
inline void operator delete[](void* ptr){ ... } calls free
int x, y;
char a, b;
etc
};
This is an ATL issue, or mixing ATL with non-ATL code.
My new operator gets called, and I know the macro has
worked in a codebase with no ATL.
I do not think adding scope resolution operators to the inline definitions
of contained functions will make any difference. I know it works, just its now being caused by ATL. Why is my problem?
This btw, also only works because my overloaded uses malloc/delete just as the ATL code does. If it used anything else, my heap would be corrupted.
exterminator
April 6th, 2006, 12:14 PM
I do not think adding scope resolution operators to the inline definitions of contained functions will make any difference. I know it works, just its now being caused by ATL. Why is my problem?Did you try atleast rather than saying it would not make any difference :mad: ? I know it may not work but not for the reason that you wrote. Also, I am interested to know if it works because I am unable to reproduce the problem that you are facing and it may help me or interested others in knowing if this is a solution. Regards.
seany
April 6th, 2006, 07:12 PM
I tried the suggestion exterminator. I created a new ATL project with struct that has overridden new and delete. I tried both with scope resolution and without. Both worked fine. I expected this. The problem is that the ATL definitions in the sample project are not as comprehensive as the one's I am dealing with in a precompiled header I use. So.....
I'm going to check using the scope operator in the current project, its just going to take time.
seany.
exterminator
April 7th, 2006, 03:43 AM
If it works as expected then what is the problem? What do you mean by the following?
.....are not as comprehensive as the one's I am dealing with in a precompiled header I use.....Regards.
seany
April 7th, 2006, 06:08 AM
It worked for the sample project, it does not work for the one I am working with - thats what I meant to say in the last post.
So I changed the code to use the scope operator and it has worked for me in my own workspace.
This is good. Thanks.
exterminator
April 7th, 2006, 08:59 AM
It worked for the sample project, it does not work for the one I am working with - thats what I meant to say in the last post.
So I changed the code to use the scope operator and it has worked for me in my own workspace.
This is good. Thanks.Okay.. so that is a good news.. :) Thank you for confirming... :)
SuperKoko
April 7th, 2006, 10:58 AM
It worked for the sample project, it does not work for the one I am working with - thats what I meant to say in the last post.
So I changed the code to use the scope operator and it has worked for me in my own workspace.
Mhh.. I would like to know the reason of that strange "bug"...
Are you sure you delete your object with a pointer to the structure (and not void*, char*, or any other pointer)!
struct S *s=new S;
delete (void*)s; // undefined behaviour
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.