Passing null pointer to placement new

风流意气都作罢 提交于 2019-11-29 22:50:53

While I can't see much of a question in there except "Has anyone ever needed placement new to correctly handle the null pointer case?" (I haven't), I think the case is interesting enough to spill some thoughts on the issue.

I consider the standard broken or incomplete wrt the placement new function and requirements to allocation functions in general.

If you look closely at the quoted §5.3.4,13, it implies that every allocation function has to be checked for a returned nullpointer, even if it is not noexcept. Therefore, it should be rewritten to

If the allocation function is declared with a non-throwing exception-specification and returns null, initialization shall not be done, the deallocation function shall not be called, and the value of the new-expression shall be null.

That would not harm the validity of allocation functions throwing exceptions, since they have to obey §3.7.4.1:

[...] If it is successful, it shall return the address of the start of a block of storage whose length in bytes shall be at least as large as the requested size. [...] The pointer returned shall be suitably aligned so that it can be converted to a pointer of any complete object type with a fundamental alignment requirement (3.11) and then used to access the object or array in the storage allocated (until the storage is explicitly deallocated by a call to a corresponding deallocation function).

And §5.3.4,14:

[ Note: when the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved. The block of storage is assumed to be appropriately aligned and of the requested size. [...] -end note ]

Obviously, a placement new that just returns the given pointer, cannot reasonably check avilable storage size and alignment. Therefore,

§18.6.1.3,1 about placement new says

[...] The provisions of (3.7.4) do not apply to these reserved placement forms of operator new and operator delete.

(I guess they missed to mention §5.3.4,14 at that place.)

However, together these paragraphs say indirectly "if you pass a garbage pointer to the palcement functions, you get UB, because §5.3.4,14 is violated". So it's up to you to check the sanity of any poitner given to placement new.

In that spirit, and with the rewritten §5.3.4,13, the standard could strip the noexcept from placement new, leading to an addition to that indirect conclusion: "...and if you pass null, you get UB as well". On the other hand, its much less likely to have a misaligned pointer or pointer to too few memory than having a null pointer.

However, this would remove the need for checking against null, and it would fit well to the philosophy "don't pay for what you don't need". The allocation function itself would not need to check, because §18.6.1.3,1 explicitly says so.

To round things up, one could consider adding a second overload

 void* operator new(std::size_t size, void* ptr, const std::nothrow_t&) noexcept;

Sadly, proposing this to the committee is unlikely to result in a change, because it would break existing code relying on placement new being ok with null pointers.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!