overload new and delete operators

Expertise: Advanced
Language: C++
April 6, 1999
Overload New and Delete in a Class
It is possible to override the global operators new and delete for a given class. For example, you can use this technique to override the default behavior of operator new in case of a failure. Instead of throwing a std::bad_alloc exception, the class-specific version of new throws a char array:

#include <cstdlib> //declarations of malloc and free
#include <new>
#include <iostream>
using namespace std;

class C {
public:
C();
void* operator new (size_t size); //implicitly declared as a static member function
void operator delete (void *p); //implicitly declared as a static member function
};

void* C::operator new (size_t size) throw (const char *){
void * p = malloc(size);
if (p == 0) throw "allocation failure"; //instead of std::bad_alloc
return p;
}

void C::operator delete (void *p){
C* pc = static_cast<C*>(p);
free(p);
}

int main() {
C *p = new C; // calls C::new
delete p; // calls C::delete
}

Note that the overloaded new and delete implicitly invoke the object's constructor and destructor, respectively. Remember also to define a matching operator delete when you override operator new.
关于原来的new operator如何定义的,我们可以试着参考下面一篇短文来得到一些启示:

An FDIS compliant Operator "new"
Rating: none

Ray Brown (view profile)
February 13, 1999

Microsoft KB article Q167733 points out that Visual C++'s implementation of operator new adopts non-FDIS compliant behavior in that it does not throw an exception in the case of an allocation failure. This may cause problems if not with your own code, then with third-party C++ code that becomes merged into your translation units. Third-party inline and template functions are especially susceptible to malfunction under the non-FDIS compliant semantics. In fact, Microsoft's own STL implementation will fail should new ever return NULL; its allocator does not expect this.

The KB article suggests a workaround that involves calling _set_new_handler. This is a good solution if you link statically with the C/C++ runtime library. But static linking is often an unpopular option among C++ developers on the Win32 platform as it increases module size and can cause a variety of other difficulties (e.g., KB Q126646, Q193462). Calling _set_new_handler from a module which links dynamically with the CRT can cause other difficulties, however, as the new handler is kept in a global variable by the CRT. Different modules in a process might thus attempt to install different new handlers, and failures will result.
(continued)

A naive FDIS compliant implementation of operator new, which might resort to malloc or some other low-level allocation routine, has the disadvantage of changing the behavior of new on the Win32 platform, especially when it comes to diagnostic support in debug mode. Unfortunately, from our own implementation of new we cannot now call CRT's new, since it becomes hidden as the compiler and linker resolve new to our own implementation. In addition, we cannot simply copy the CRT's implementation as it makes use of CRT functions that are not exported.

In what follows we present an implementation of ::operator new that does not suffer from any of the problems outlined above. This solution's key consists of locating CRT's operator new address dynamically, and avoiding the repeated overhead of module search through the use of a static object.

Note that if your module links with MFC, then you should not adopt this solution. MFC provides its own operator new, which throws a CMemoryException* on allocation failure. This is necessary as MFC exception handlers expect all exceptions to be derived from MFC's CException base class. While this has the potential of upsetting third-party code for similar reasons as the FDIS non-compliance mentioned above, such code often works as long as some exception is thrown from new and NULL is never returned. Microsoft's STL appears to fall in this category. Code which expects std::bad_alloc on new failure cannot co-exist peacefully with MFC in a module.

<!--content_stop-->

Microsoft KB article Q167733 points out that Visual C++'s implementation of operator new adopts non-FDIS compliant behavior in that it does not throw an exception in the case of an allocation failure. This may cause problems if not with your own code, then with third-party C++ code that becomes merged into your translation units. Third-party inline and template functions are especially susceptible to malfunction under the non-FDIS compliant semantics. In fact, Microsoft's own STL implementation will fail should new ever return NULL; its allocator does not expect this.

The KB article suggests a workaround that involves calling _set_new_handler. This is a good solution if you link statically with the C/C++ runtime library. But static linking is often an unpopular option among C++ developers on the Win32 platform as it increases module size and can cause a variety of other difficulties (e.g., KB Q126646, Q193462). Calling _set_new_handler from a module which links dynamically with the CRT can cause other difficulties, however, as the new handler is kept in a global variable by the CRT. Different modules in a process might thus attempt to install different new handlers, and failures will result.
(continued)

A naive FDIS compliant implementation of operator new, which might resort to malloc or some other low-level allocation routine, has the disadvantage of changing the behavior of new on the Win32 platform, especially when it comes to diagnostic support in debug mode. Unfortunately, from our own implementation of new we cannot now call CRT's new, since it becomes hidden as the compiler and linker resolve new to our own implementation. In addition, we cannot simply copy the CRT's implementation as it makes use of CRT functions that are not exported.

In what follows we present an implementation of ::operator new that does not suffer from any of the problems outlined above. This solution's key consists of locating CRT's operator new address dynamically, and avoiding the repeated overhead of module search through the use of a static object.

Note that if your module links with MFC, then you should not adopt this solution. MFC provides its own operator new, which throws a CMemoryException* on allocation failure. This is necessary as MFC exception handlers expect all exceptions to be derived from MFC's CException base class. While this has the potential of upsetting third-party code for similar reasons as the FDIS non-compliance mentioned above, such code often works as long as some exception is thrown from new and NULL is never returned. Microsoft's STL appears to fall in this category. Code which expects std::bad_alloc on new failure cannot co-exist peacefully with MFC in a module.

<!--content_stop-->

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值