瘦身未使用的 std::stringstream 语言环境/分面以供嵌入式使用?

slimming unused std::stringstream locale/facets for embedded use?

提问人:Shabble 提问时间:11/28/2022 更新时间:11/28/2022 访问量:153

问:

我目前正在为 C++ 中的低规格 ARM Cortex M4 构建一个应用程序,使用静态链接的 stdlibc++。arm-none-eabi-g++

代码的某些部分目前用于构造用于各种目的的字符串,并且很难从代码库中删除/重构。std::stringstream

代码的一个相当基本的子集,所有字符串流都垫片

(通过标题,如下所示:fakestream.h

namespace blah {
    class stringstream {
        stringstream() {}
        ~stringstream() {}
        std::string str() {
           return "dummy";
        }
        template<typename T>
        stringstream& operator<<(T val) {
           return *this;
        }
    };
}

随着调用更改为:

#include "fakestream.h"
using blah::stringstream;
...
stringstream ss; 
ss << ...

与使用 std::stringstream 相比,从应用程序中修剪大约 350kB 的代码。

我意识到确实需要一些代码,但是当使用 bloaty 检查生成的 .elf 时, 很多空间似乎都被以下功能占用了:

     6.5%  20.0Ki    std::num_get<>::_M_extract_int<>()
     3.7%  11.3Ki    std::__cxx11::money_get<>::_M_extract<>()
     2.9%  8.97Ki    std::money_get<>::_M_extract<>()
     2.7%  8.24Ki    d_print_comp_inner
     2.3%  6.97Ki    _svfprintf_r
     2.1%  6.42Ki    _svfwprintf_r
     2.0%  6.11Ki    __strftime.isra.0
     2.0%  6.09Ki    __ssvfscanf_r
     1.8%  5.61Ki    __ssvfiscanf_r
     1.8%  5.54Ki    std::__cxx11::time_get<>::_M_extract_via_format()
     1.5%  4.65Ki    std::num_get<>::_M_extract_float()
     1.4%  4.29Ki    std::__cxx11::money_put<>::_M_insert<>()
     1.4%  4.24Ki    std::num_get<>::do_get()
     1.4%  4.17Ki    std::__moneypunct_cache<>::_M_cache()
     1.3%  3.96Ki    _strtod_l
     1.3%  3.89Ki    _vfiprintf_r
     1.3%  3.87Ki    std::time_get<>::_M_extract_via_format()
     1.2%  3.81Ki    _dtoa_r
     1.2%  3.64Ki    std::money_put<>::_M_insert<>()
     1.1%  3.53Ki    std::locale::_Impl::_Impl()
     1.1%  3.28Ki    std::__facet_shims::__moneypunct_fill_cache<>()
     1.1%  3.27Ki    _svfiprintf_r
     1.0%  3.21Ki    std::num_put<>::_M_insert_int<>()
     0.8%  2.54Ki    std::num_put<>::_M_insert_float<>()
     0.7%  2.11Ki    d_type
     0.6%  1.94Ki    std::__cxx11::time_get<>::_M_extract_name()

而且我确信我没有对 stringstream 或其他任何地方使用任何或相关的类/值。moneytime

据我所知,可能会发生一些与区域设置相关的间接操作,或者允许根据活动区域设置对这些类型进行格式化,但我在此应用程序中不需要任何这些。iosios_base

是否有可能以某种方式表明这些功能是不必要的,应该从最终输出中省略?

理想情况下,可以继续直接使用,但将其替换为代理或类似内容(但这实际上委托了格式化基本整数类型、字符串和一些自定义对象重载的必要功能)。std::stringstream

C++ 嵌入式 C++14 标准 代码大小

评论

0赞 273K 11/28/2022
是否启用编译器优化?
0赞 rturrado 11/28/2022
我不知道在这种情况下使用库而不是 s 是否可行。如果是,那就值得一试了。fmtstringstream
0赞 Shabble 11/28/2022
我尝试过 G++ 中的 、 和 优化。它对整体二进制大小产生了(相当小的)差异,但我认为这主要是在我的代码中而不是库代码中,臃肿仍然显示为存在,并且大小完全相同(正如我所期望的那样,如果它不重新编译 libstdc++ 库每次都不会受到优化级别的影响 - 尽管也许模板会以不同的方式扩展?我真的不知道)-O0-Og-Os
1赞 Lundin 11/29/2022
这是我能给出的最好的理由:ISO C 9899:2018 有一个 20 页长的细则列表,简要总结了标准中明确定义不明确的所有行为形式。C++没有这样的列表,可能是因为摘要是一本与ISO 14882本身一样厚的书。我不确定是否曾尝试过整理这样的清单。如果你找到了这个列表,那么这就是你不使用 C++(在嵌入式系统中)的最佳理由。
1赞 Sedenion 11/30/2022
@Shabble 您是否知道“嵌入式模板库”(ETL)?我从未亲自使用过它,但它确实有一个字符串流。此外,也许升压性能更好;他们至少在文档中提到了嵌入式环境。

答: 暂无答案