部分MLE会显示RE
程序在申请内存时,被操作系统拒绝,malloc返回NULL。一般选手程序不会对申请失败进行判断,从而导致了RE而不是MLE
设置 setrlimit 之后,如果静态数组过大的的话 execve 失败,errno = ENOMEM,如果动态分配内存过大的话 brk 或 mmap 失败,errno = ENOMEM
这个是程序处理的问题,如果选手程序没有处理 malloc 返回 NULL 的情况,那么就是一个空指针错误。但在这里不应该将 「malloc 返回 NULL」认为是一种「错误」。
man malloc 镇层。
The
malloc()andcalloc()functions return a pointer to the allocated memory, which is suitably aligned for any built-in type. On error, these functions returnNULL.
我觉得如果按照 @Menci 的说法的话,动态分配内存出现 MLE 是不可能判出来的,因为我可以比如写一个数据结构,只有当 malloc 返回 NULL 时才会开始回收内存,以求提高效率。
所以似乎写清楚一些?至少 Runtime Error (Memory Limit Exceeded) 是可以确定的。
如果选手的程序是C++,且用new申请的内存空间超过了rlimit,就会throw掉,所以会把这些MLE判成RE。如果选手的程序是数组开大了、递归太深了、malloc太多了,就能正常判断出MLE。
解决方法:
编译时如果遇到C++代码,先g++ -E 预处理代码,然后把现有的new (std::nothrow)替换new,然后再把new全部替换成new (std::nothrow)。
或者不用setrlimit,然后ptrace跟踪子进程的系统调用,在SYS_brk调用返回时检查一下进程的内存使用大小。
改库使得malloc失败就是MLE