lucasart wrote:marcelk wrote:lucasart wrote:
so it's very simple, just check the errno and that's it.
If you do it like that you get false errors: malloc doesn't clear errno in case of success. Errno is used to communicate the reason of failure, not the failure itself.
Just check for NULL returned out of malloc.
(you can of course clear errno yourself before the function call, but that is not idiomatic)
PS: In case of realloc, beware to store the return value first in a different location than the input parameter. Because in case of failure, the old region is still allocated. If you do "p = realloc(p, ...)" you have a memory leak in case of failure.
Thanks! Although that's really the correct way to proceed according to the ISO C standard, in reality a failed malloc or realloc crashes Windows and causes Linux to unleash the OOM killer, killing "randomly" chosen processes to save memory. So really, there's no need to handle the case of a failed memory allocation
No, a failed malloc() does not necessarily crash the system. That depends on the available amount of virtual memory. Under Linux there is usually plenty of that available. The point is, as soon as virtual memory is really being used above the available amount of RAM (i.e., you write into memory areas that are actually mapped to swap space on disk) the system is slowing down a lot.
The "OOM killer" of Linux will only jump in if also the swap space is exhausted. That may be the case if no swap space, or only a tiny amount of it, has been configured, or if some applications have allocated a lot of memory without ever freeing it. In a normally working system you should never observe the "OOM killer" scenario.
I am not quite sure about the exact behaviour of Windows in case of virtual memory being exhausted. Most probably Windows will not handle that case more smoothly than Linux. But at least there is a virtual memory concept that works somehow, using something like a swap file, so malloc() and related allocation functions are able to allocate more memory than you have unused RAM available.
For a chess engine, though, you will not like to come into a situation where the OS has to access swap space. Therefore an approach like Steven's to find out how much RAM is really available for the program is highly recommended.
Conclusions:
1) If you use C++ with exceptions (usually not in a chess program) then use the "new" operator and deal with exceptions at an appropriate point. You can safely assume that the return value of "new" is non-zero (otherwise exception handling control flow does not guide you to the next statement behind the call of "new").
2) If you use C++ without exceptions then use "new", too, and check the pointer returned by "new" against 0. To allocate arrays use new[] accordingly. To dynamically resize allocated memory areas use either delete[] and new[] or realloc().
3) If you use plain C then you have to use malloc() or realloc(). Always check its return value against NULL. Don't care about "errno", especially don't look at "errno" without having checked for occurrence of an error itself. This is common UNIX philosophy: "errno" indicates the reason of an error if there is any, but is undefined in the default case that there isn't any (otherwise all system calls would have to set errno=0 in the beginning each time which is a waste of CPU time).
4) In any case, define a proper reaction on a failed memory allocation. Apart from not using the returned pointer (since it is 0), you need to define what that "out of memory" case really means for you. If the amount of memory to be allocated was defined by some external parameter, like a hash table size specified by the user, then use a smaller value. Of course early rejecting the user's request based on knowing how much memory is available is even better, but conditions may become worse at runtime so you still need to check every time. If the memory allocation is crucial for your program to continue its work and trying to allocate a smaller amount of memory is not an option then abort the program after giving appropriate feedback.
Chess programs will not need "new" or malloc() too often, I use it only to allocate my hash table.
Merry christmas,
Sven