全局重载删除[]未在第三方库中调用

DSM*_*DSM 6 c++ memory-management

我正在尝试学习C++中的内存池,以获得更好的速度和调试功能.我一直在关注这里找到的方法:http://oroboro.com/overloading-operator-new/.所以,我已经超负荷new,new[],delete,和delete[]这样的:

inline void* operator new     ( size_t size ) { return myAlloc( size ); }
inline void* operator new[]   ( size_t size ) { return myAlloc( size ); }
inline void  operator delete  ( void* ptr   ) { myFree( ptr ); }
inline void  operator delete[]( void* ptr   ) { myFree( ptr ); }
Run Code Online (Sandbox Code Playgroud)

我喜欢第三方库是针对这个版本的new,但我遇到了一个问题.我正在制作一个使用DXUT 的DirectX应用程序.我从我的项目中单独编译DXUT.最终它呼吁:

std::unique_ptr<D3D11_SUBRESOURCE_DATA[]> initData( new (std::nothrow) D3D11_SUBRESOURCE_DATA[ mipCount * arraySize ] );
Run Code Online (Sandbox Code Playgroud)

一旦这个唯一指针超出范围,它就会在调用时崩溃delete[] _Ptr,而调用 没有通过我的重载操作符.我尝试通过添加一个int* dummy = new int[10]; delete[] dummy;in my来调试我的内存池实现main.建立项目给出了错误,但清洁建设工作正常.令我惊讶的是,一切正常,包括崩溃的DXUT系列!

问题1:当我添加修复问题的调试行时到底发生了什么?我想由于某些原因我的操作符delete []在我用我自己的应用程序代码调用它之前是不知道的?这可以保证解决问题还是只是运气不好?

问题2:我注意到new (std::nothrow) D3D11_SUBRESOURCE_DATA[ mipCount * arraySize ]没有operator new[]直接打电话给我,但最终打电话给我operator new(没有括号).它仍然delete[]在指针上调用操作符.这会造成问题吗?我是否必须添加适当的重载,以便operator new[]调用我或这种行为是否合适?

作为参考,operator new[]调用的重载是:

void * __CRTDECL operator new[](::size_t count, const std::nothrow_t& x)
_THROW0()
{ // Try to allocate count bytes for an array
    return (operator new(count, x));
}
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 4

\n

问题 1:当我添加解决问题的调试行时,到底发生了什么?我想由于某种原因,直到我在自己的应用程序代码中调用它之前,我的运算符delete[] 才被知道?这是否能保证解决问题,还是只是运气不好?

\n
\n\n

\xc2\xa73.2 [basic.def.odr]/p4:

\n\n
\n

内联函数应在使用 odr 的每个翻译单元中定义。

\n
\n\n

听起来您的编译器没有为全局生成代码,operator delete[]因为它没有在您的主翻译单元中使用并且被标记inline(这意味着编译器可以假设任何使用它们的翻译单元都会有它们的定义)。但是,您单独编译的库没有这些函数的定义,您最终只能使用标准库中的默认函数。使他们非inline应该可以解决问题。

\n\n
\n

问题2:我注意到thenew (std::nothrow) D3D11_SUBRESOURCE_DATA[ mipCount * arraySize ]并没有 operator new[]直接调用my\n,而是最终调用了my operator new(没有\n括号)。它仍然delete[]在指针上调用运算符。\n 这会带来问题吗?我是否必须添加适当的重载,\noperator new[]调用 my ,或者这种行为正常吗?

\n
\n\n

的抛出版本和非抛出版本operator new []以及 的非抛出版本的默认operator new版本都被指定为调用 的抛出版本operator new来获取内存。所以你在那里很安全。然而,你的operator new定义可能是错误的。它们必须返回有效的指针或抛出异常。不允许返回空指针。

\n