有没有办法在 c++ 中使用异常而不会使我增加 60k 的二进制大小?

Posted

技术标签:

【中文标题】有没有办法在 c++ 中使用异常而不会使我增加 60k 的二进制大小?【英文标题】:Is there a way to use exceptions in c++ that doesn't cost me 60k in added binary size? 【发布时间】:2013-02-07 21:43:10 【问题描述】:

我在一个嵌入式平台上工作,我不习惯将 60k 添加到我的二进制文件中。无论如何,在嵌入式系统上都有避免异常的论据,但我认为它们中的大多数都是虚假的。例外是有道理的,但我无法证明目前的成本是合理的。我正在使用 gcc 4.6.3,也许我错过了一个选项,或者这可能只是异常的开销。我试过-Os,并将例外更改为longjmp,但无济于事。我可能错过了什么。

感谢您的任何见解。

【问题讨论】:

“例外是有道理的,但我无法证明目前的成本是合理的” - 那么,在这种情况下,它们真的没有意义,是吗? Bot 方法有利有弊,但使用错误代码并没有错(除了大量添加的样板代码)。把这些做对也容易得多。 这可能对***.com/questions/998248/…有帮助 @EdS。不,你是对的。由于目前的成本,它们没有意义,所以我目前没有使用它们。我的问题是我是否可以以某种方式降低成本。我现在正在使用错误代码。 @MrUniverse:当你有 256k 的内存可以使用时会很多。我在更少的平台上工作过。 @MrUniverse:这在某种程度上很有趣(我喜欢编写让物理实体四处移动、发光等的软件)。但有时会令人沮丧……我们曾经不得不重写代码生成引擎,因为它生成的代码太大了。 【参考方案1】:

第一次,没有!

异常处理需要一些成本,主要是需要 RTTI 支持,恕我直言(目前还没有通过实验证明这一点)。 RTTI 支持会导致代码文本段的一些费用使用,特别是如果有很多模板实例化(例如,广泛使用具有多种类型的 STL 模板类/容器类)。

另一方面,与其他减少的可能性相比,例如newlib 所需的实现,60k 开销的成本并没有那么多。

您真的应该三思而后行放弃异常支持!

很有趣,我今天和我的同事讨论了这个话题,当时我们面临一个明显由内存不足情况引起的错误。有问题的固件(以及它与 FreeRTOS 的操作系统绑定)不支持异常,但如果您无法使用 new() 获取一定数量的堆内存,内存管理实现会触发处理器异常。这可能在使用一些 STL 诱导算法时发生,并且您没有机会在失败时使用 try/catch 块来拦截它(例如,使用简单的 std::vector)。

因此,您应该决定如何处理错误情况,不使用或不使用异常,并确保提供一致的行为,例如使用常见的 STL 模式等,并权衡您为.text 部分大小支付的成本。

【讨论】:

【参考方案2】:

您可以使用-fno-exceptions 关闭 GCC 中的异常。

但是,你不能一边吃蛋糕一边吃。关闭异常意味着您无法捕获它们,如果您链​​接到使用异常编译的代码,它也会中断。但它确实如您所愿减少了二进制大小。

没有异常的代码(但具有相同级别的错误检查)就像罪恶一样丑陋,但这是你必须付出的代价。

C 语言中可爱的无异常健壮代码示例 :)

error_t foo(void) 
    if (!do_foo()) 
        error_code = E_FOO;
        goto bail;
    
    if (!do_bar()) 
        error_code = E_BAR;
        goto bail;
    
    /* repeat 100 times */
bail:
    cleanup();
    return error_code;

【讨论】:

这不会使 OP 按照他/她的要求实际使用异常。是的,你不能边吃边吃蛋糕...... 更好地衡量添加的混淆是否真的给你带来了任何尺寸方面的东西(额外的错误处理代码也会出现)。 @vonbrand 不用测量,相差60k量级。等效的 try/catch/throws 和 if/cleanup/errors 之间的大小差异可以忽略不计。 @CongXu,我不太确定,两者都相当复杂(编译器生成或手写)。堆栈展开也可能存在一些运行时开销。

以上是关于有没有办法在 c++ 中使用异常而不会使我增加 60k 的二进制大小?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 C++ 中捕获所有异常? [复制]

try catch 事务不会滚

使用 TQDM 几乎使我的 GET 请求的文件大小增加了一倍

限制列表控件 MFC 中的条目数

在混合 C 和 C++ 代码编程中捕获异常后对象不会被破坏

为啥大型本地数组会使我的程序崩溃,而全局数组却不会? [复制]