Language agnostic 是";“内存不足”;可恢复的错误?

Language agnostic 是";“内存不足”;可恢复的错误?,language-agnostic,exception,memory,memory-management,error-recovery,Language Agnostic,Exception,Memory,Memory Management,Error Recovery,我已经编写了很长一段时间了,我看到的程序,当内存用完时,会尝试清理并退出,即正常地失败。我不记得我最后一次看到有人试图恢复并继续正常工作是什么时候了 如此多的处理依赖于能够成功地分配内存,特别是在垃圾收集语言中,似乎内存不足的错误应该被归类为不可恢复的。(不可恢复的错误包括堆栈溢出等。) 使其成为可恢复错误的有力论据是什么?在一般情况下,它是不可恢复的 但是,如果系统包含某种形式的动态缓存,则内存不足处理程序通常可以转储缓存(甚至整个缓存)中最旧的元素 当然,您必须确保“转储”过程不需要新的内存

我已经编写了很长一段时间了,我看到的程序,当内存用完时,会尝试清理并退出,即正常地失败。我不记得我最后一次看到有人试图恢复并继续正常工作是什么时候了

如此多的处理依赖于能够成功地分配内存,特别是在垃圾收集语言中,似乎内存不足的错误应该被归类为不可恢复的。(不可恢复的错误包括堆栈溢出等。)


使其成为可恢复错误的有力论据是什么?

在一般情况下,它是不可恢复的

但是,如果系统包含某种形式的动态缓存,则内存不足处理程序通常可以转储缓存(甚至整个缓存)中最旧的元素


当然,您必须确保“转储”过程不需要新的内存分配:)此外,恢复失败的特定分配可能很棘手,除非您能够在分配器级别直接插入缓存转储代码,因此,故障不会传播到调用方。

这实际上取决于您正在构建什么


Web服务器使一个请求/响应对失败,然后继续进行进一步的请求,这并不是完全不合理的。但是,你必须确保单一的失败不会对全局状态产生有害影响——这将是一个棘手的问题。考虑到在大多数托管环境(例如NET和Java)中,故障会导致异常,我怀疑如果在“用户代码”中处理异常,它将在将来的请求中恢复—例如,如果一个请求尝试分配10GB内存但失败,这不应损害系统的其余部分。但是,如果系统在试图将请求传递给用户代码时内存不足,那么这种情况可能会更糟糕。

这是一个困难的问题。乍一看,似乎没有更多的记忆意味着“运气不好”,但你也必须看到,如果一个人真的坚持,他可以摆脱许多与记忆有关的东西。让我们从另一方面来看,函数strtok是坏的,一方面,它在内存方面没有问题。然后将Glib库中的g_string_分割作为对应项,Glib库与基于Glib或GObject的程序中的几乎所有内容一样严重依赖于内存分配。我们可以肯定地说,在更为动态的语言中,内存分配比在更为死板的语言(尤其是C语言)中使用得更多。但让我们看看替代方法。如果在内存不足时结束程序,即使是精心开发的代码也可能停止工作。但是,如果您有一个可恢复的错误,您可以对此采取一些措施。因此,使其可恢复的论点意味着人们可以选择以不同的方式“处理”这种情况(例如,为紧急情况留出内存块,或降级为内存不足的程序)

因此,最令人信服的原因是。如果你提供了一种恢复方法,你可以尝试恢复,如果你没有选择,一切都取决于总是获得足够的内存


关于

我认为与许多事情一样,这是一个成本/收益分析。您可以在尝试从malloc()故障中恢复时进行编程,尽管这可能很困难(您的处理程序最好不要与它要处理的内存不足问题相冲突)

您已经注意到,最常见的情况是清理并优雅地失败。在这种情况下,可以确定正常中止的成本低于恢复过程中开发成本和性能成本的总和


我相信你能想到你自己的例子,在这种情况下,终止该计划是一个非常昂贵的选择(生命支持机器、宇宙飞船控制、长期运行和时间关键型财务计算等)-尽管第一道防线当然是确保程序具有可预测的内存使用量,并且环境可以提供这些内存使用量。

在库中,您希望高效地复制文件。当您这样做时,您通常会发现使用少量大数据块进行复制比复制大量小数据块更有效(例如,通过复制15 1MB数据块来复制15MB文件比复制15 000 1K数据块更快)

但是代码可以处理任何块大小。因此,虽然1MB数据块可能更快,但如果您设计的系统复制了大量文件,那么明智的做法可能是抓住内存错误的机会,减小数据块大小,直到成功

另一个地方是数据库中存储的对象的缓存。您希望在缓存中保留尽可能多的对象,但不希望干扰应用程序的其余部分。由于这些对象可以重新创建,因此将缓存附加到内存不足处理程序以删除条目,直到应用程序的其余部分有足够的空间呼吸,这是一种节省内存的聪明方法

最后,对于图像处理,您希望将尽可能多的图像加载到内存中。同样,OOM处理程序允许您在不预先知道用户或操作系统将授予代码多少内存的情况下实现该功能


[编辑]请注意,我在这里的工作假设是,您为应用程序提供了固定的内存量,该内存量小于不包括交换空间的总可用内存量。如果您可以分配如此多的内存,以致部分内存必须调出,那么我的一些评论就不再有意义了。

我正在开发一个为IO缓存分配内存以提高性能的系统。然后,在检测到OOM时,它会收回部分OOM,这样业务逻辑就可以继续,即使这意味着IO缓存更少,写性能也会稍微降低

我还使用了一个嵌入式Java应用程序,该应用程序试图通过强制垃圾收集来管理OOM,可以选择释放一些非关键对象,如预取或缓存的数据

OOM处理的主要问题是:

1) abl
T new2(T)( lazy T old_new ) {
    T obj;
    try{
        obj = old_new;
    }catch(OutOfMemoryException oome) {
        foreach(compact; Global_List_Of_Delegates_From_Compatible_Objects)
            compact();
        obj = old_new;
    }
    return obj;
}
void *smalloc(size_t size) {
  void *mem = null; 
  for(;;) {
   mem = malloc(size);
   if(mem == NULL) {
    sleep(1);
   } else 
     break;
  }
  return mem;
}