是否可以完全禁用默认的C ++ new运算符? [英] Is it possible to completely disable the default C++ new operator?

查看:205
本文介绍了是否可以完全禁用默认的C ++ new运算符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因为我们的应用程序具有硬性能和内存限制,我们的编码标准禁止使用默认堆—即,没有 malloc ,没有默认。每个内存分配必须选择几个特定分配器之一;类似

Because our app has hard performance and memory constraints, our coding standards forbid the use of the default heap — ie, no malloc, no default new. Every memory allocation has to choose one of a few specific allocators; something like

// declared globally
void* operator new( size_t size, CustomAllocHeap* heap, const char* perpetrator_name )
{
  return heap->Allocate( size, perpetrator_name );
} 
// imagine a bunch of CustomAllocHeap's declared globally or statically, thus

Vector* v = new( gPhysicsHeap, __FUNCTION__ ) Vector( 1.0f, 2.0f, 3.0f, 4.0f );
// or in a class
Thingy* p = new( this->LocalArenaHeap, __FUNCTION__ ) Thingy();

虽然我们使用我们的代码保持了良好的纪律,一些标准的C ++组件code> std :: function )隐藏地调用默认的 new 堆,这是非常糟糕的。

Although we've maintained good discipline on this with our code, some standard C++ components ( containers, std::function ) covertly make calls to the default new heap, which is very bad.

以某种方式禁用默认的 new 将是很好的,所以任何代码行隐式导致一个默认分配立即抛出一个编译错误。这将让我们马上注意到这些事情。

It would be nice to disable the default new altogether in some way, so that any line of code that implicitly results in a default allocation immediately throws a compiler error. That would let us notice these things right away.

我们可以明显使 new

We can obviously make new throw a runtime error ie

void* operator new ( size_t ) { __debugbreak(); return NULL; }  

但在编译时获取警告更好。这是可能吗?

but it would be much better to get warnings about this at compile time. Is that possible?

我们的应用程序是为一个固定平台(x64与Visual Studio);可移植性是无关紧要的。

Our app is built for a fixed platform (x64 with Visual Studio); portability is irrelevant.

推荐答案

您可以实现默认 new 未实现的功能。然后,在链接时,您会收到一个错误给裸的调用的用户:

You can implement the default new to call an unimplemented function. Then, at link time, you will get an error to the users of the bare new call:

#include <stdexcept>
inline void * operator new (std::size_t) throw(std::bad_alloc) {
    extern void *bare_new_erroneously_called();
    return bare_new_erroneously_called();
}



。 com / tPMiXcrel =nofollow> IDEONE ,我收到此错误:

/home/geXgjE/ccrEKfzG.o: In function `main':
prog.cpp:(.text.startup+0xa): undefined reference to `bare_new_erroneously_called()'
collect2: error: ld returned 1 exit status

在我的测试中,使用 g ++ 链接错误,如果没有引用到程序中裸的 new 。这是因为 g ++ 不会为未使用的 inline 函数释放代码。

In my tests, using g++, there is no link error if there are no references to the bare new in the program. This is because g++ does not emit code for unused inline functions.

我没有在我的系统上安装Visual Studio,所以以下信息仅基于我发​​现的一些文档。为了获得内联的 new 运算符,你应该把它的定义放在头文件中,然后使用 / FI detect_bare_new.h 选项。 > * 根据此答案,Visual Studio不会为未使用的内联函数(如 g ++ )。但是,您应该检查是否需要为该行为启用优化级别。

I don't have Visual Studio installed on my system, so the following information is just based on some documentation I have found. In order to get the inlined new operator to be seen everywhere, you should put its definition in a header file, and then use the /FI detect_bare_new.h option in your compiler.* According to this answer, Visual Studio will not generate code for unused inline functions (like g++). However, you should check to see if there is an optimization level that needs to be enabled for that behavior or not.


* g ++ 有类似的编译器选项: -include detect_bare_new.h

* g++ has a similar compiler option: -include detect_bare_new.h.

这假设您打算通过自己的分配器到C ++模板和标准C ++库中的类。如果不这样做,那么调用默认分配器(它将调用 new )的标准头文件中的内联代码也将触发链接错误。如果你希望允许标准C ++库使用默认的 new ,那么一个简单的方法使它工作(以更长的编译时间为代价)是添加所有您打算在 detect_bare_new.h 文件的顶部添加标准C ++头。

This assumes that you intend to pass your own allocators to C++ templates and classes in the standard C++ library. If you do not, then inlined code in the standard headers that call the default allocator (which will call new) will trigger the linking error as well. If you wish to allow the standard C++ library to use the default new, then an easy way to make it work (at the expense of longer compile times) is to add all the standard C++ headers you intend to include at the top of the detect_bare_new.h file.

您声明可移植性解决方案对你来说不重要。但为了完整性,我应该强调Ben Voigt正确指出的问题:C ++标准不保证不为未使用的 inline 函数生成代码的行为。因此,即使不使用函数,也可能会产生链接错误。但是,如果代码没有对未实现的函数的其他引用,除非在桩的 new 实现中,错误将在 new 定义本身。例如, g ++ 可能会产生如下错误:

You state that portability of the solution is not important to you. But for the sake of completeness, I should highlight the issue that Ben Voigt correctly points out: The C++ standard does not guarantee the behavior of not generating code for unused inline functions. So, one may get a linking error even if the function is not used. But, if the code has no other references to the unimplemented function except within the stubbed new implementation, the error would be within the new definition itself. For example, g++ could generate an error like:

/home/QixX3R/cczri4AW.o: In function `operator new(unsigned int)':
prog.cpp:(.text+0x1): undefined reference to `bare_new_erroneously_called()'
collect2: error: ld returned 1 exit status

如果您的系统是生成未使用的 inline 函数,你可能仍有一个解决方法。如果链接器报告对未定义函数的所有错误引用,则解决方法将有效。在这种情况下,如果观察到的唯一的链接错误是由于 new 运算符本身的定义,没有意外调用裸的 new 。在验证代码只有单个错误后,您可以更改链接行以包括具有适当定义 bare_new_erroneously_called()的对象或库,它将抛出运行时异常。

If your system is one that generates code for unused inline functions, you may still have a workaround. The workaround will work if the linker will report all erroneous references to the undefined function. In that case, if the only linking error observed is due to the definition of the new operator itself, there are no unexpected calls to the bare new. After verifying that the code only has that single error, you could then change the link line to include an object or library that has an appropriate definition of bare_new_erroneously_called() that would throw a runtime exception.

这篇关于是否可以完全禁用默认的C ++ new运算符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆