Reading through the UE source code, I come across a few places that test the return value of the new operator against NULL.
In normal C++, this shouldn’t ever be necessary, and the standard C++ runtime library will throw an exception if there is not enough memory (before calling constructors, which may also throw exceptions.)
Does Unreal Engine override the standard library behavior for calling new? Can new return NULL in this engine?
New is operator that can be overrided in any class as any other overridable operator(it’s not global thing), so why don’t you check operator override decleration on class that new been used on yourself? If i check then class probably do
Thanks for your comment. However, I am asking about the new operator, which is distinct from (but makes use of) the function named operator new(). The new operator is responsible for calling constructors and making sure objects get their run-time type signature, and is not user-replaceable.
Separately, if I were to verify the absence of a specific overridden member function in the Unreal code, that would actually be surprisingly hard, because of the heavy use of macros and the deep inheritance chains used.
I figure it’s better to actually ask if there is an engine-level strategy in this area rather than trying to describe this particular elephant by poking at its trunk myself.
Separately, the documentation I have found about this talks about UObject management, but the code I’m reading (part of navmesh building) uses straight new / delete. I can’t find any mention of low-level memory management at all in the “official documentation” section.
The specific code that made me wonder was in ARecastNavMesh, although what that code made me want to know was what the documented strategy is for the engine, not that particular case. If the strategy for Unreal includes replacing the compiler runtime, that’s hard to tell from just looking at an individual tree in the forest.
if (AgentProps.IsValid())
{
Generator = new FRecastNavMeshGenerator(this);
if (Generator != NULL)
{
#if RECAST_ASYNC_REBUILDING
NavDataReadWriteLock = Generator->GetNavMeshModificationLock();
#endif // RECAST_ASYNC_REBUILDING
}
}
Just following the classes up to TSharedFromThis<> seems to indicate that neither the new operator or operator new is touched in this case (and the if() above is unnecessary) but I find it’s easy to miss things if there’s some global approach I’m not aware of. Hence, the question about what the global approach is
I’m sorry, I don’t understand how that answers the question. You will note that the code path that leads up to this code already makes sure it’s thread exclusive. I’m not currently worried about whether != is overridden; I’m worried about whether there is a global approach to memory management that affects bare new expressions. (This is not uncommon in C++ game engines.)
UObject and UStruct types overload operator new via one of the nested macros within GENERATED_UCLASS_BODY and GENERATED_USTRUCT_BODY. Slate widgets also override this operator, as do modules via REPLACEMENT_OPERATOR_NEW_AND_DELETE.
The module level replacement seems to catch all the allocations made within a module, even if you’re not allocating a UObject, UStruct, or Slate widget.
Ultimately they call through to FMemory::Malloc, which will forward it onto whichever allocator is active (eg, FMallocTBB). If one of these allocators fails to perform an allocation, they will call an implementation specific OutOfMemory function to log a fatal error.
I tried allocating 0x7fffffffffffffff bytes. With a debugger attached, it broke into the debugger on the failed allocation; without a debugger attached, the application just quit.
Thanks! So I can still rely on new never returning NULL. I’ll copy your answer into the Wiki, too (there was an article on memory, but it didn’t talk about new at all.)