代码之家  ›  专栏  ›  技术社区  ›  Loris

你是否经常检查C++新指令中的异常?

  •  8
  • Loris  · 技术社区  · 16 年前

    这本书很好地解释了如何(以不同的优雅程度)捕获std::bad_alloc异常,如果内存不足,new操作符会引发该异常。

    10 回复  |  直到 16 年前
        1
  •  17
  •   Rob Kennedy    16 年前

    当我能回答这个问题时,我捕捉到异常:

    一旦捕捉到异常,您将如何处理它?

    大多数时候,我的回答是,“我不知道。也许我的来电者知道。”所以我没有发现异常。让那些更了解情况的人知道。

    std::bad_alloc ,您不应该再内存不足了。您不应该只从函数返回错误代码,因为调用方必须显式地检查该错误代码,而您的内存仍然不足。您对该异常的处理应该会释放一些内存。清空一些缓存,将一些东西提交到磁盘,等等。但是,您真正想负责减少程序内存使用的程序中有多少函数?

    如果无法解决触发异常的问题,则不要处理异常。

        2
  •  7
  •   Edouard A.    16 年前

    问题是,当内存耗尽时,除了写入崩溃转储并退出程序外,通常没有什么可以做的。因此,检查程序中的每一个新项都是无用的。

    这种情况的一个例外是,当您为加载文件分配内存时,在这种情况下,您只需通知用户没有足够的内存用于请求的操作。

        3
  •  4
  •   wilhelmtell    16 年前

    Curiously Recurring Template 从这个基类派生的模式。然后,您的派生类将优雅地处理错误的分配,但您仍然需要记住在您创建的每个新类上从该基类派生。通常,您可能会以多重继承结束,这可能会带来自身的复杂性。无论您如何处理错误的分配,您的代码都不会像您不费事那样简单。

    这个问题从来没有一个答案。这是一个你必须做出的选择,取决于上下文。

        4
  •  4
  •   Daniel Daranas    16 年前

    从不我一直认为默认行为(有一个std::bad_alloc异常,它没有被处理,因此程序以错误消息终止)对于我工作过的应用程序来说是好的。

        5
  •  3
  •   peterchen    16 年前

    你至少可以告诉用户,他实际上已经耗尽了内存,至少可以给他(或支持)一个线索,说明应用程序为什么会随机崩溃。

    如果你能给出一个错误信息,比如“你不能插入这个图像,因为你的内存不足”,那就太好了。你会继续工作,就像什么都没发生一样。但是,这意味着用户命令背后的所有代码都必须是事务性的,并提供 strong exception safety guarantee .


    因此,请确定随机耗尽内存的成本。在此基础上,评估您需要为用户提供的“保护级别”。

        6
  •  2
  •   Community CDub    5 年前

    我认为这在很大程度上取决于您编写的应用程序的类型。如果我写的东西不影响系统的全局稳定性,比如说一个游戏或一个电影播放器,我不会检查这个例外。我的申请会打电话给你 std::terminate

    如果我编写一个程序,其稳定性直接对应于它所运行的系统之一,比如视频驱动程序或init系统,我会一直检查内存异常(可能在函数中包装分配),并在分配失败的情况下从预分配的池中获取一些内存。

    我认为这一切都取决于比例。如果一个稳定得惊人的电影播放器因为你的攻击性检查而开始放慢播放速度,你会从中得到什么?

    顺便说一句,有人回答说,当某些系统的内存不足时,malloc不会返回0。没错,但正如malloc的主页所指出的(特定于linux)

    如果Linux是在不太希望突然丢失一些随机挑选的进程的情况下使用的,而且内核版本足够新,可以使用以下命令关闭这种过度交付行为: $ echo 2 > /proc/sys/vm/overcommit_memory

    另请参阅内核文档目录,文件vm/overmit accounting和sysctl/vm.txt。

        7
  •  2
  •   jmizv 박준성    3 年前

    在使用虚拟内存的系统中, malloc() 不会再回来了 NULL ,新的将不会返回 std::bad_alloc

    所以你抓住了 标准:坏的 当你在一个没有MMU的嵌入式系统上,希望你能做点什么来释放一些内存。

        8
  •  0
  •   Stefan    16 年前

    如果您必须为路径缓冲区分配内存,而您知道它只有几个字节,那么这可能不值得这么麻烦。

    但是,当您必须为较大的对象(如图像或文件)分配内存时,您肯定应该进行检查。

        9
  •  0
  •   ReaperUnreal    16 年前

    除非您使用类似于RAII(资源获取是初始化)模式的东西,否则这通常是不值得的。在这种情况下,您可能会在构造函数中分配远程资源,这可能包括使用new来创建一个大的缓冲区。

        10
  •  0
  •   MSalters    16 年前

    不过,没有通用的处理策略。任何实现了缓存的进程都应该刷新这些缓存,但是当操作系统发出内存不足的信号时,一个好的缓存应该已经被刷新了。响应用户请求的进程可以在用户请求粒度上处理错误分配。如果用户操作的内存不足,保持内存分配通常没有什么好处。相反,请恢复到用户操作之前的状态。另一方面,非交互式进程可能会从O(N)算法切换到较慢的O(N logn)算法。