Programing

임베디드 C ++ : STL 사용 여부?

lottogame 2020. 11. 1. 17:13
반응형

임베디드 C ++ : STL 사용 여부?


저는 항상 임베디드 소프트웨어 엔지니어 였지만 일반적으로 OSI 스택의 레이어 3 또는 2에 있습니다. 나는 정말로 하드웨어 전문가가 아닙니다. 나는 일반적으로 일반적으로 ARM 7 프로세서와 같은 것을 의미하는 일반적으로 손 / 휴대 전화와 같은 통신 제품을 사용했습니다.

이제 저는 좀 더 일반적인 임베디드 세계, 작은 스타트 업에서 "그다지 강력하지 않은"프로세서 (주관적인 부분이 있음)로 이동할 수 있습니다. 어느 것이인지 예측할 수 없습니다.

임베디드 시스템의 C ++에서 STL을 사용하는 것에 대한 토론에 대해 꽤 많이 읽었으며 명확한 답은 없습니다. 이식성에 대한 약간의 우려와 코드 크기 또는 런타임에 대한 약간의 우려가 있지만 두 가지 주요 우려 사항이 있습니다.
1-예외 처리; 나는 여전히 그것을 사용할지 확실하지 않다 ( 임베디드 C ++ : 예외 를 사용 하느냐 말지 ? )
2-나는 그것이 도입 할 수있는 문제 때문에 임베디드 시스템에서 동적 메모리 할당을 매우 싫어한다. 일반적으로 컴파일 시간에 정적으로 할당되고 고정 크기 버퍼 만 제공하는 버퍼 풀이 있습니다 (버퍼가 없으면 시스템 재설정). 물론 STL은 많은 동적 할당을 수행합니다.

이제 저는 STL을 사용할 것인지 아니면 포기할 것인지 결정해야합니다.-회사 전체를 위해 영원히 (아주 핵심적인 소프트웨어에 들어가는 중입니다).

나는 어느 방향으로 점프합니까? 매우 안전하고 C ++를 구성하는 많은 부분을 잃고 (imo, 언어 정의 이상임) 나중에 문제가 발생하거나 많은 예외 처리 및 다른 코드를 지금 추가해야 할 수 있습니까?

난 그냥 갈 안넘어 부스트 하지만, 그들이 / 보증을하지 않습니다 그것의 특정 부분을 권장하는 것이 자신의 웹 사이트에있는 모든 내장 내가 사용하는 것이 좋습니다 프로세서와 2)에 포트를 말할 것이다 경우 1) 나는 확실하지 않다 임베디드 시스템 (특히 이상해 보이는 FSM)의 경우. 부스트에 가서 나중에 문제를 찾으면 ....


매우 안전하고 C ++를 구성하는 많은 부분을 잃고 (imo, 언어 정의 이상임) 나중에 문제가 발생하거나 많은 예외 처리 및 다른 코드를 지금 추가해야 할 수 있습니까?

우리는 게임 세계에서 비슷한 논쟁을 벌이고 있으며 사람들은 양쪽으로 내려옵니다. 인용 된 부분과 관련하여 "C ++를 구성하는 많은 부분"을 잃어 버리는 것에 대해 왜 걱정하십니까? 실용적이지 않다면 사용하지 마십시오. "C ++"인지 아닌지는 중요하지 않습니다.

몇 가지 테스트를 실행하십시오. 만족스러운 방식으로 STL의 메모리 관리를 처리 할 수 ​​있습니까? 그렇다면 노력할만한 가치가 있었습니까? 많은 문제 STL과 부스트는 단순한 동적 메모리 할당을 피하기 위해 설계하는 경우 발생하지 않는 단순한 해결을 위해 설계되었습니다. STL이 직면 한 특정 문제를 해결합니까?

많은 사람들이 빡빡한 환경에서 STL을 다루었으며 이에 만족했습니다. 많은 사람들이 그것을 피합니다. 어떤 사람들은 완전히 새로운 표준을 제안 합니다 . 정답이 하나도 없다고 생각합니다.


저는 매일 실시간 임베디드 시스템에서 작업합니다. 물론 임베디드 시스템에 대한 나의 정의는 당신과 다를 수 있습니다. 그러나 우리는 STL과 예외를 최대한 활용하고 관리 할 수없는 문제를 경험하지 않습니다. 또한 동적 메모리 (매우 빠른 속도, 초당 많은 패킷 할당 등)를 사용하며 아직 사용자 지정 할당 자 또는 메모리 풀에 의존 할 필요가 없습니다. 인터럽트 처리기에서도 C ++를 사용했습니다. 우리는 부스트를 사용하지 않지만 특정 정부 기관에서 허용하지 않기 때문입니다.

머리를 사용하고 자체 벤치 마크를 수행하는 한 임베디드 환경에서 많은 최신 C ++ 기능을 실제로 사용할 수있는 것은 우리의 경험입니다. Sutter 및 Alexandrescu의 C ++ 코딩 표준 뿐만 아니라 Scott Meyer의 효과적인 C ++ 3 판을 사용하여 정상적인 프로그래밍 스타일로 C ++를 사용하는 데 도움 이되도록 적극 권장합니다 .

편집 : 2 년 후이 항목에 대한 찬성 투표를받은 후 업데이트를 게시하겠습니다. 우리는 개발 과정에서 훨씬 더 멀어졌고 마침내 표준 라이브러리 컨테이너가 고성능 조건에서 너무 느린 코드를 발견했습니다. 여기서 우리는 실제로 사용자 지정 알고리즘, 메모리 풀 및 단순화 된 컨테이너에 의존했습니다. 이것이 C ++의 아름다움입니다. 표준 라이브러리를 사용하고 사용 사례의 90 %에 대해 제공하는 모든 좋은 것을 얻을 수 있습니다. 문제가 발생할 때 모든 것을 버리는 것이 아니라 문제 지점을 직접 최적화하기 만하면됩니다.


다른 게시물에서는 동적 메모리 할당, 예외 및 가능한 코드 팽창의 중요한 문제를 다루었습니다. 추가하고 싶습니다 : 잊지 마세요 <algorithm>! 에 관계없이 STL 벡터 또는 일반 C 배열과 포인터 사용 여부, 당신은 여전히 사용할 수 있습니다 sort(), binary_search(), random_shuffle(),, 구축 및 힙을 관리하는 기능 등이 루틴은 거의 확실 빠르고 적은 버그 당신이 자신을 만들 버전보다됩니다.

예 : 신중하게 생각하지 않는 한, 직접 만든 셔플 알고리즘 은 왜곡 된 분포를 생성 할 수 있습니다 . random_shuffle()습관.


Electronic Arts는 STL이 임베디드 콘솔 개발에 적합하지 않은 이유와 자체적으로 작성해야하는 이유에 대한 긴 논문썼습니다 . 자세한 기사이지만 가장 중요한 이유는 다음과 같습니다.

  1. STL 할당자는 느리고 비대하며 비효율적입니다.
  2. 컴파일러는 실제로 모든 심층 함수 호출을 인라인하는 데 능숙하지 않습니다.
  3. STL 할당자는 명시 적 정렬을 지원하지 않습니다.
  4. GCC 및 MSVC의 STL과 함께 제공되는 STL 알고리즘은 플랫폼에 구애받지 않고 큰 차이를 만들 수있는 많은 마이크로 최적화를 놓치기 때문에 성능이 좋지 않습니다.

몇 년 전, 우리 회사는 STL을 전혀 사용하지 않기로 결정했습니다. 대신에 최대한 성능이 뛰어나고 디버깅하기 쉬우 며 메모리가 더 보수적 인 자체 컨테이너 시스템을 구현했습니다. 많은 일 이었지만 여러 번 갚았습니다. 그러나 우리의 공간은 주어진 CPU와 메모리 크기로 16.6ms에 얼마나 들어갈 수 있는지 제품이 경쟁하는 공간입니다.

예외에 관해서 콘솔에서 느리며 달리 알려주는 사람은 타이밍을 시도하지 않았습니다. 활성화 된 상태로 컴파일하면 필요한 프롤로그 / 에피 로그 코드로 인해 전체 프로그램 속도가 느려집니다. 저를 믿지 않는다면 직접 측정하세요. x86보다 순차 CPU에서 더 나쁩니다. 이러한 이유로 우리가 사용하는 컴파일러는 C ++ 예외도 지원하지 않습니다.

성능 향상은 예외 발생 비용을 피할 때가 아니라 예외를 완전히 비활성화하는 것입니다.


제가 몇 년 동안 임베디드 작업을 해본 적이없고 C ++로도 작업하지 않았기 때문에 제 충고는 여러분이 지불하는 모든 페니의 가치가 있습니다.

STL에서 사용하는 템플릿은 사용자가 직접 생성 할 필요가없는 코드를 생성하지 않으므로 코드 부풀림에 대해 걱정하지 않습니다.

STL은 자체적으로 예외를 발생시키지 않으므로 걱정할 필요가 없습니다. 수업이 던지지 않으면 안전해야합니다. 객체 초기화를 두 부분으로 나누고 생성자가 베어 본 객체를 생성하도록 한 다음 오류 코드를 반환하는 멤버 함수에서 실패 할 수있는 초기화를 수행합니다.

모든 컨테이너 클래스를 사용하면 자신 만의 할당 기능을 정의 할 수 있으므로 풀에서 할당하려는 경우이를 수행 할 수 있습니다.


  1. 메모리 관리를 위해 풀에서 메모리를 요청하는 자체 할당자를 구현할 수 있습니다. 그리고 모든 STL 컨테이너에는 할당 자에 대한 템플릿이 있습니다.

  2. 예외의 경우 STL은 많은 예외를 발생시키지 않습니다. 일반적으로 가장 일반적인 경우는 메모리 부족, 귀하의 경우 시스템이 재설정되어야하므로 할당 자에서 재설정 할 수 있습니다. 다른 것들은 범위를 벗어난 것과 같이 사용자가 피할 수 있습니다.

  3. 그래서 임베디드 시스템에서 STL을 사용할 수 있다고 생각합니다. :)


오픈 소스 프로젝트 "Embedded Template Library (ETL)" 는 라이브러리를 제공 / 구현하여 임베디드 애플리케이션에서 사용되는 STL의 일반적인 문제를 대상으로합니다.

  • 결정 론적 행동
  • "컴파일시 크기 또는 최대 크기가 결정되는 컨테이너 집합을 만듭니다. 이러한 컨테이너는 호환되는 API를 사용하여 STL에 제공된 컨테이너와 거의 동일해야합니다."
  • 동적 메모리 할당 없음
  • RTTI가 필요하지 않음
  • 가상 기능을 거의 사용하지 않음 (절대적으로 필요한 경우에만)
  • 고정 용량 컨테이너 세트
  • 지속적으로 할당 된 메모리 블록으로 컨테이너의 캐시 친화적 스토리지
  • 컨테이너 코드 크기 감소
  • 형식이 안전한 스마트 열거 형
  • CRC 계산
  • 체크섬 및 해시 함수
  • 변형 = 일종의 유형 안전 공용체
  • 어설 션, 예외, 오류 처리기 또는 오류 검사 없음 선택
  • 많은 단위 테스트
  • 잘 문서화 된 소스 코드
  • 및 기타 기능 ...

ESR Labs에서 제공하는 임베디드 개발자 용 상용 C ++ STL을 고려할 수도 있습니다 .


It basically depends on your compiler and in the amount of memory you have. If you have more than a few Kb of ram, having dynamic memory allocation helps a lot. If the implementation of malloc from the standard library that you have is not tuned to your memory size you can write your own, or there are nice examples around such as mm_malloc from Ralph Hempel that you can use to write your new and delete operators on top.

I don't agree with those that repeat the meme that exceptions and stl containers are too slow, or too bloated etc. Of course it adds a little more code than a simple C's malloc, but judicious use of exceptions can make code much clear and avoid too much error checking blurb in C.

One has to keep in mind that STL allocators will increase their allocations in powers of two, which means sometimes it will do some reallocations until it reaches the correct size, which you can prevent with reserve so it becomes as cheap as one malloc of the desired size if you know the size to allocate anyway.

If you have a big buffer in a vector for example, at some point it might do a reallocation and ends using up 1.5x the memory size that you are intending it to use at some point while reallocating and moving data. (For example, at some point it has N bytes allocated, you add data via append or an insertion iterator and it allocates 2N bytes, copies the first N and releases N. You have 3N bytes allocated at some point).

So in the end it has a lot of advantages, and pays of if you know what you are doing. You should know a little of how C++ works to use it on embedded projects without surprises.

And to the guy of the fixed buffers and reset, you can always reset inside the new operator or whatever if you are out of memory, but that would mean you did a bad design that can exhaust your memory.

An exception being thrown with ARM realview 3.1:

--- OSD\#1504 throw fapi_error("OSDHANDLER_BitBlitFill",res);
   S:218E72F0 E1A00000  MOV      r0,r0
   S:218E72F4 E58D0004  STR      r0,[sp,#4]
   S:218E72F8 E1A02000  MOV      r2,r0
   S:218E72FC E24F109C  ADR      r1,{pc}-0x94 ; 0x218e7268
   S:218E7300 E28D0010  ADD      r0,sp,#0x10
   S:218E7304 FA0621E3  BLX      _ZNSsC1EPKcRKSaIcE       <0x21a6fa98>
   S:218E7308 E1A0B000  MOV      r11,r0
   S:218E730C E1A0200A  MOV      r2,r10
   S:218E7310 E1A01000  MOV      r1,r0
   S:218E7314 E28D0014  ADD      r0,sp,#0x14
   S:218E7318 EB05C35F  BL       fapi_error::fapi_error   <0x21a5809c>
   S:218E731C E3A00008  MOV      r0,#8
   S:218E7320 FA056C58  BLX      __cxa_allocate_exception <0x21a42488>
   S:218E7324 E58D0008  STR      r0,[sp,#8]
   S:218E7328 E28D1014  ADD      r1,sp,#0x14
   S:218E732C EB05C340  BL       _ZN10fapi_errorC1ERKS_   <0x21a58034>
   S:218E7330 E58D0008  STR      r0,[sp,#8]
   S:218E7334 E28D0014  ADD      r0,sp,#0x14
   S:218E7338 EB05C36E  BL       _ZN10fapi_errorD1Ev      <0x21a580f8>
   S:218E733C E51F2F98  LDR      r2,0x218e63ac            <OSD\#1126>
   S:218E7340 E51F1F98  LDR      r1,0x218e63b0            <OSD\#1126>
   S:218E7344 E59D0008  LDR      r0,[sp,#8]
   S:218E7348 FB056D05  BLX      __cxa_throw              <0x21a42766>

Doesn't seem so scary, and no overhead is added inside {} blocks or functions if the exception isn't thrown.


In addition to all comments, I would propose you reading of Technical Report on C++ Performance which specifically addresses topics that you are interested in: using C++ in embedded (including hard real-time systems); how exception-handling usually implemented and which overhead it has; free store allocation's overhead.

The report is really good as is debunks many popular tails about C++ performance.


The biggest problem with STL in embedded systems is the memory allocation issue (which, as you said, causes a lot of problems).

I'd seriously research creating your own memory management, built by overriding the new/delete operators. I'm pretty sure that with a bit of time, it can be done, and it's almost certainly worth it.

As for the exceptions issue, I wouldn't go there. Exceptions are a serious slowdown of your code, because they cause every single block ({ }) to have code before and after, allowing the catching of the exception and the destruction of any objects contained within. I don't have hard data on this on hand, but every time I've seen this issue come up, I've seen overwhelming evidence of a massive slowdown caused by using exceptions.

Edit:
Since a lot of people wrote comments stating that exception handling is not slower, I thought I'd add this little note (thanks for the people who wrote this in comments, I thought it'd be good to add it here).

The reason exception handling slows down your code is because the compiler must make sure that every block ({}), from the place an exception is thrown to the place it is dealt with, must deallocate any objects within it. This is code that is added to every block, regardless of whether anyone ever throws an exception or not (since the compiler can't tell at compile time whether this block will be part of an exception "chain").

Of course, this might be an old way of doing things that has gotten much faster in newer compilers (I'm not exactly up-to-date on C++ compiler optimizations). The best way to know is just to run some sample code, with exceptions turned on and off (and which includes a few nested functions), and time the difference.


On our embedded scanner project we were developing a board with ARM7 CPU and STL didn't bring any issue. Surely the project details are important since dynamic memory allocation may not be an issue for many available boards today and type of projects.

참고URL : https://stackoverflow.com/questions/2226252/embedded-c-to-use-stl-or-not

반응형