嵌入式C++:是否使用STL?

Maw*_*awg 71 c++ embedded stl

我一直是一名嵌入式软件工程师,但通常在OSI堆栈的第3层或第2层.我不是一个硬件家伙.我一般都经常使用电信产品,通常是手机/手机,这通常意味着像ARM 7处理器.

现在我发现自己处于一个更通用的嵌入式世界中,在一个小型的初创公司中,我可能会转向"不那么强大"的处理器(这是主观位) - 我无法预测哪个.

我已经阅读了很多关于在嵌入式系统中使用C++在C++中的争论,而且没有明确的答案.有一些关于可移植性的小担忧,还有一些关于代码大小或运行时的问题,但我有两个主要问题:
1 - 异常处理; 我仍然不确定是否使用它(参见嵌入式C++:是否使用异常?)
2 - 我非常不喜欢嵌入式系统中的动态内存分配,因为它可能会引入问题.我通常有一个缓冲池,它在编译时静态分配,只提供固定大小的缓冲区(如果没有缓冲区,系统复位).当然,STL会进行大量的动态分配.

现在我必须决定是否使用或放弃STL - 对于整个公司,永远(它进入一些非常核心的s/w).

我跳哪个方向?超级安全并且失去了很多构成C++的东西(imo,它不仅仅是语言定义),可能会在以后遇到问题,或者现在必须添加大量的异常处理和其他一些代码?

我很想和Boost一起去,但是1)我不确定它是否会移植到我可能想要使用的每个嵌入式处理器上2)在他们的网站上,他们说他们不保证/推荐它的某些部分对于嵌入式系统(尤其是FSM,这似乎很奇怪).如果我选择Boost,我们会在以后发现问题....

Bri*_*eal 45

我每天都在使用实时嵌入式系统.当然,我对嵌入式系统的定义可能与您的不同.但是我们充分利用STL和异常,并且不会遇到任何无法解决的问题.我们还使用动态内存(以非常高的速率;每秒分配大量数据包等)并且还不需要求助于任何自定义分配器或内存池.我们甚至在中断处理程序中使用了C++.我们不使用提升,只是因为某个政府机构不会让我们这么做.

根据我们的经验,只要您使用头脑并执行自己的基准测试,就可以在嵌入式环境中使用许多现代C++功能.我强烈建议您使用Scott Meyer的Effective C++第3版以及Sutter和Alexandrescu的C++编码标准来帮助您使用具有理智编程风格的C++.

编辑:2年后获得upvote后,让我发布更新.我们在开发过程中走得更远,最终在我们的代码中遇到了标准库容器在高性能条件下速度太慢的问题.实际上,我们在这里采用了自定义算法,内存池和简化容器.这就是C++的美妙之处,你可以使用标准库并获得它为90%的用例提供的所有好东西.当你遇到问题时,你不会全力以赴,只需手动优化故障点.

  • +1,有用的答案.但是我认为你并不像你认为的那样了解异常或代码臃肿 - 请在别人的帖子中看到我对你的评论. (3认同)

Dan*_*son 33

超级安全并且失去了很多构成C++的东西(imo,它不仅仅是语言定义),可能会在以后遇到问题,或者现在必须添加大量的异常处理和其他一些代码?

我们在游戏世界中也有类似的争论,人们双方都有所下降.关于引用的部分,为什么你会担心失去"C++的大部分内容"?如果它不实用,请不要使用它.它是否是"C++"并不重要.

运行一些测试.您能以满足您需求的方式绕过STL的内存管理吗?如果是这样,是否值得努力?很多问题STL和boost的设计只是简单解决如果你的设计是为了避免偶然的动态内存分配... STL是否解决了你面临的特定问题?

很多人在紧张的环境中处理STL并对此感到满意.很多人都避免它.有些人提出了全新的标准.我不认为有一个正确的答案.


j_r*_*ker 25

其他帖子已经解决了动态内存分配,异常和可能的代码膨胀等重要问题.我只想补充一点:别忘了<algorithm>!不管你是否使用STL向量或普通的C数组和指针,你仍然可以使用sort(),binary_search(),random_shuffle(),用于构建和管理堆,功能等等.这些程序几乎肯定比你自己构建的版本速度更快,bug更少.

示例:除非您仔细考虑,否则您自己构建的随机算法可能会产生偏差分布 ; random_shuffle()惯于.


Cra*_*rks 19

Electronic Arts撰写了一篇冗长的论文,阐述了为什么STL不适合嵌入式控制台开发,以及为什么他们必须自己编写.这是一篇详细的文章,但最重要的原因是:

  1. STL分配器缓慢,膨胀且效率低下
  2. 编译器实际上并不擅长内联所有那些深层函数调用
  3. STL分配器不支持显式对齐
  4. GCC和MSVC的STL附带的STL算法效率不高,因为它们与平台无关,因此错过了许多可以产生重大影响的微优化.

几年前,我们公司决定不使用STL,而是实现我们自己的容器系统,这些容器具有最高性能,更易于调试和更保守的内存.这是很多工作,但它已经多次偿还.但是我们的产品是一个空间,在这个空间中,产品可以通过给定的CPU和内存大小来争夺16.6ms.

至于例外情况:它们在游戏机上很慢,任何告诉你的人都没有尝试计时.简单地使用它们进行编译会因为必要的prolog/epilog代码而减慢整个程序的速度 - 如果你不相信我自己测量它.在有序CPU上比在x86上更糟糕.因此,我们使用的编译器甚至不支持C++异常.

性能提升并不是避免异常抛出的成本 - 而是完全禁用异常.

  • 像Herb Sutter和Andrei Alexandrescu这样的公认C++专家不同意你的"异常缓慢"的说法.如果您不使用异常,那么您自己现在负责编写和检查错误返回代码,并且此代码的​​效率几乎总是低于现代编译器为异常发出的代码.此外,人们编写的代码(如果他们根本没有写它)来检查错误代码通常会出现错误和错误. (15认同)
  • 您已经链接了2006年的一篇文章,该文章现已过时.在体面的现代编译器上,C++异常并不慢.如果你正在处理一个不存在体面的现代copmiler的嵌入式系统,你就会遇到问题 - 但要给出一个"如果例外:它们很慢"的说法是错误的. (12认同)
  • 这篇文章是从2006年开始的,但*我自己的*时间是从2009年8月开始的.我已经阅读了关于异常如何不再缓慢的所有理论**但是他们没有证实我已经采取的实际测量**. (10认同)
  • 异常并不是很慢,但即使没有抛出任何异常,它们也会在至少一个流行的现代编译器(MSVC++ 9)上施加非零运行时开销.要看到这一点,尝试编译(不链接)http://pastebin.com/m1fb29a45与`/ EHa`然后使用`/ EHsc`,使用/ Fa生成汇编列表.在这两种情况下,都引入了Win32结构化异常处理(SEH)管理 - 即将数据推送到堆栈并设置`FS`段寄存器. (4认同)
  • 布莱恩:那些是EA的观点,不是我的,但#4是凭经验确定的.基本上,他们编写了自己的容器实现,并发现它们的运行速度比STL快得多.因此,STL不是最有效的. (2认同)
  • 知名专家喜欢数据分析时不同意"红皮书盲读"总是正确的说法. (2认同)

Mar*_*som 15

让我先说我几年没有完成嵌入式工作,而且从来没有用过C++,所以我的建议值得为你付出的每一分钱......

STL使用的模板永远不会生成您不需要自己生成的代码,所以我不担心代码膨胀.

STL不会自行抛出异常,所以这不应该是一个问题.如果你的课不扔,你应该是安全的.将对象初始化分为两部分,让构造函数创建一个裸骨对象,然后在返回错误代码的成员函数中执行任何可能失败的初始化.

我认为所有的容器类都可以让你定义自己的分配函数,所以如果你想从池中分配你可以实现它.

  • 你是什​​么意思"STL不会自己抛出异常"?如果你用超出范围的索引调用vector :: at怎么办?您还可以配置IO流以引发异常.此外,模板可以生成比您手动编写的代码更多的代码.请参阅Stroustrup中关于将模板与void*组合以减少此类膨胀的示例. (5认同)
  • @Brian:`vector :: at()`就是一个很好的例子.更准确地说,STL可以以这样的方式使用它永远不会产生异常(这里,通过使用`operator []()`而不是`at()`)并且不做任何额外的妥协. (4认同)

ddh*_*ddh 5

  1. 对于内存管理,您可以实现自己的分配器,它从池中请求内存.并且所有STL容器都有分配器的模板.

  2. 对于异常,STL不会抛出很多异常,一般来说,最常见的是:内存不足,在你的情况下,系统应该重置,所以你可以在分配器中做复位.其他如超出范围,您可以避免它被用户.

  3. 所以,我认为你可以在嵌入式系统中使用STL :)


thi*_*ybk 5

开源项目“嵌入式模板库(ETL)”通过提供/实现一个库来解决嵌入式应用程序中使用的STL的常见问题:

  • 确定性行为
  • “创建一组在编译时确定大小或最大大小的容器。这些容器应在很大程度上与STL中提供的那些容器相同,并具有兼容的API。”
  • 没有动态内存分配
  • 无需RTTI
  • 很少使用虚拟功能(仅在绝对必要时使用)
  • 固定容量的容器一套
  • 容器的缓存友好存储作为连续分配的存储块
  • 减少容器代码大小
  • 类型安全的智能枚举
  • CRC计算
  • 校验和和哈希函数
  • 变体=类型的安全联合的种类
  • 选择断言,异常,错误处理程序或不检查错误
  • 经过大量单元测试
  • 有据可查的源代码
  • 和其他功能...

您还可以考虑由ESR Labs提供的面向嵌入式开发人员的商业C ++ STL