C ++는 임베디드 시스템에 적합합니까?


167

여기와 다른 곳에서 일반적인 질문입니다. C ++는 임베디드 시스템에 적합합니까?

마이크로 컨트롤러? RTOS? 토스터? 임베디드 PC?

마이크로 컨트롤러에서 OOP가 유용한가요?

C ++는 프로그래머를 하드웨어에서 너무 멀리 제거하여 효율적입니까?

Arduino의 C ++ (동적 메모리 관리, 템플릿, 예외가없는)를 "실제 C ++"로 간주해야합니까?

(이 위키는이 잠재적 인 거룩한 전쟁을 담을 장소가 될 것입니다)


5
빠른 질문 : 임베디드 라고 할 때 마이크로 컨트롤러를 의미합니까? 마이크로 프로세서? 임베디드 x86 / 임베디드 PC?
J. Polfer

1
나는 거룩한 전쟁을 일으키려하지 않았다. 의도는 당신의 주장이 무엇에 반대하는지 배우는 것이 었습니다.
J. Polfer

2
전에 몇 가지 질문이 있었으므로 중심 장소가 좋을 것이라고 생각했습니다.
Toby Jaffey 2016 년

4
C ++ 대 임베디드는 논쟁의 여지가있는 주제입니다. 나는 강한 의견을 가지고 있지만, 질문을 제기하고 점수를 얻는 것이 공정하다고 생각하지 않았습니다. 커뮤니티 위키가보다 균형 잡힌 토론을 할 수 있기를 바랍니다.
Toby Jaffey 2016 년

13
"내장 된"은 특정 언어와 관련 수하물이 적합한 지 여부를 결정하는 데 의미가 없기 때문에 이것은 나쁜 질문입니다. 요점은 작은 시스템과 큰 시스템입니다. 소형 시스템은 OS를 실행하지 않고 메모리가 제한적이며 폰 노이 먼이 아닐 수 있으며 호출 스택, 데이터 스택에 대한 다양한 하드웨어 제한이있을 수 있습니다 .Mb를 동적으로 할당 할 수는 없습니다 또는 kb 등. 대부분의 마이크로 컨트롤러는 "소형"시스템입니다. 단일 보드 컴퓨터는 일반적으로 내장되어 있지만 일반적으로 "대형"시스템입니다.
Olin Lathrop

답변:


135

예, C ++은 여전히 ​​임베디드 시스템에서 유용합니다. 다른 사람들이 말했듯이 8 비트 uC는 아마도 컴파일러가 있고 어떤 사람들은 그것을 할지라도 내 책에는 전혀없는 것처럼 시스템 자체에 달려 있습니다. 8 비트 마이크로 세계에서도 C ++을 "C +"로 축소 할 때에도 C ++을 사용하는 것이 여전히 유리합니다. "C +"는 무엇을 의미합니까? 나는 새로운 / 삭제를 사용하지 말고, 예외를 피하고, 상속을 가진 가상 클래스를 피하고, 상속을 함께 피하고, 템플릿을 매우 조심하고, 매크로 대신 인라인 함수를 사용하고, const대신 변수를 사용 하십시오 #defines.

저는 10 년 이상 임베디드 시스템에서 C와 C ++ 모두에서 일해 왔으며 C ++에 대한 저의 젊은 열정은 순진한 일부 실제 문제로 인해 분명히 사라졌습니다. 임베디드 시스템에서 C ++의 최악의 상황을 보았습니다. "EE 세계에서 CS 프로그래머가 열광했습니다." 사실, 그것은 내가 가지고있는이 하나의 코드베이스를 향상시키기 위해 클라이언트와 협력하고 있습니다.

C ++의 위험은 언어와 일반 프로그래밍 자체에서 제대로 교육 받고 훈련되지 않으면 팔과 다리를 모두자를 수있는 양날 칼과 매우 유사한 도구이기 때문에 매우 강력합니다. C는 단검과 비슷하지만 여전히 날카 롭습니다. C ++을 사용하면 매우 높은 수준의 추상화를 얻는 것이 너무 쉽고 장기적으로 무의미한 난독 처리 된 인터페이스를 만들 수 있으며 이는 부분적으로 많은 다른 언어 기능 (템플릿, OOP, 절차, RTTI, OOP + 템플릿, 과부하, 인라인).

C ++ 전문가 인 Scott Meyers가 C ++ 임베디드 소프트웨어에 대해 2 시간 동안 4 시간 동안 세미나를 마쳤습니다. 그는 이전에는 고려하지 않은 템플릿과 안전에 중요한 코드를 만드는 데 얼마나 도움이 될 수 있는지에 대해 언급했습니다. 이것의 핵심은 엄격한 안전에 중요한 코드 요구 사항을 충족해야하는 소프트웨어에서 데드 코드를 가질 수 없다는 것입니다. 컴파일러는 템플릿을 인스턴스화 할 때 필요한 코드 만 생성하므로 템플릿을 사용하면 도움이됩니다. 그러나 링커가 항상 데드 코드를 최적화하지는 않기 때문에 C에서는 달성하기 어려운이 기능을 올바르게 설계하기 위해 사용에 대해 철저하게 교육을 받아야합니다.

Scott Meyers는 템플릿과 인라인의 신중한 사용에 대해 매우 큰 지지자이며 템플릿에 대해 쿵쾅 거리는 것에 대해 여전히 회의적입니다. 비록 그들이 최고의 도구가되는 곳에만 적용되어야한다고 말하지만, 나는 그들로부터 부끄러워하는 경향이 있습니다. 또한 C ++은 올바른 인터페이스를 사용하기 쉽고 올바르게 사용하기 어려운 인터페이스를 만드는 도구를 제공한다고 지적합니다. 다시 말하지만, 그것은 어려운 부분입니다. 최고의 디자인 솔루션이되기 위해 가장 효율적인 방법으로 이러한 기능을 적용하는 방법을 알기 전에 C ++에서 어느 정도 숙달해야합니다.

OOP도 마찬가지입니다. 임베디드 세계에서는 런타임 다형성의 런타임 비용을 처리 할 수 ​​있는지 알기 위해 컴파일러가 어떤 종류의 코드를 뱉어 낼 것인지 숙지해야합니다. 설계가 마감일 요구 사항을 충족한다는 것을 증명하기 위해 기꺼이 측정을 수행해야합니다. 새로운 InterruptManager 클래스가 인터럽트 대기 시간을 너무 길게 만들 수 있습니까? C가 할 수있는 링크 타임 다형성과 같은 문제에 더 잘 맞는 다형성의 다른 형태가 있지만 C ++은 Pimpl 디자인 패턴 (불투명 포인터)을 통해 수행 할 수 있습니다 .

C ++은 임베디드 세계에서 그 자리를 차지하고 있습니다. 당신이 원하는 모든 것을 미워할 수는 있지만 사라지지는 않습니다. 매우 효율적인 방식으로 작성 될 수 있지만 C보다 올바르게 수행하는 방법을 배우기가 더 어렵습니다. 문제를 해결하고 더 나은 인터페이스를 표현할 때 C보다 더 잘 작동 할 수 있지만 다시 한 번, 자신을 교육하고 방법을 배우는 것을 두려워하지 마십시오.


1
이것은 다른 임베디드 시스템 컨설턴트가 읽은 내용과 일치합니다. 나는 항상 C로, 당신은 끊임없이 작은 방식으로 자아를 자르지 만 C ++의 버그는 더 드물게 될 것이지만, 망칠 때 다리를 잃을 것입니다. 내가 가지고 있지 않은 전문 지식으로 명확한 답변을 작성해 주셔서 감사합니다.
Kortuk

3
EE 땅에서 컴퓨터 과학 전공이 미쳐 가고 있다는 점에 주목하십시오. 내 직업에서 우리가 가진 최악의 코드는 CS 전공이 작성했습니다. 우리는 그에게 하드웨어가 무엇인지 가르치려고 영원히 노력했습니다. 그는 UML을 사용하여 구조화 된 시스템을 만들고 적절한 상속 등을 사용하여이를 기반으로 전체 시스템을 Java로 구축했습니다. 모든 것이 바뀌기 전까지는 효과가 있었고 기능을 추가하거나 완전히 재 설계하는 것은 나쁜 패치 작업이었습니다. 코드가 상속을 통해 전체를 난독 화했기 때문에 코드를 거의 사용할 수 없습니다.
Kortuk

2
그것은 당신을 물린 버그 일뿐 만 아니라 당신을 물릴 수없는 유지 할 수없는 코드입니다. 물론, 깔끔한 C ++ 기능을 사용하여 프로젝트를 시작할 때 모든 것이 웅장 해지지 만 2 ~ 3 년 후에 엔트로피가 발전하면서 리팩토링에 심각한 노력을 기울이지 않으면 엔트로피가 시작됩니다. 그것이 내가 지금 직면하고있는 것입니다. 코드는 C ++에서 시간이 지남에 따라 더 빨리 썩습니다.
Jay Atkinson 2016 년

2
UML 및 상태 머신. state-machine.com 에서 Miro Samek의 자료를 살펴보십시오 . 그는 리팩토링과 변경이 쉬운 효율적인 시스템을 구축했지만 시간이 많이 걸립니다.
Jay Atkinson 2016 년

2
실제로 시스템과 사용 가능한 메모리 양에 따라 다릅니다. RAM이 거의없는 8 비트 마이크로 코드를 작성하고 있습니까? 그렇다면 추상 인터페이스에 열중하지 않는 것이 좋습니다. 메모리가 많은 32 비트 임베디드 시스템과 같은 것을 쓰고 있다면 그것을 찾으십시오. 당신은 정말로 그것을 무게를 측정해야합니다. 예를 들어, 해당 클래스에서 월드를 "가상"으로 사용할 때마다 해당 객체를 선언하는 모든 단일 인스턴스에 대해 시스템에 따라 8 비트, 16 비트 또는 32 비트 일 수있는 추가 포인터가 제공됩니다. 당신은, 실현, 그리고 사람이되지 않습니다
제이 앳킨슨

56

C ++는 임베디드 시스템에 절대적으로 적합합니다. 이제 특정 마이크로 프로세서를 사용할지 여부에 대한 기본 기준으로 우수한 개발 도구의 유무 (또는 부족)를 사용합니다.

리소스 비용이 낮기 때문에 임베디드 시스템에서 사용하기에 좋은 C ++ 영역 :

  • 클래스 / 구조를 잘 활용하여 모듈화
  • 컴파일러가 효율적으로 컴파일하는 데 도움이되는 경우 템플릿 . 템플릿은 다른 데이터 유형에 알고리즘을 재사용 할 수있는 유용한 도구입니다.

확인 영역 :

  • 가상 함수-나는 이것에 반대했지만 리소스 비용은 매우 작습니다 ( 객체가 아닌 클래스 당 하나의 vtable, 객체 당 vtable에 대한 포인터 하나, 가상 함수 호출 당 하나의 역 참조 작업) 및 이것의 큰 장점 어떤 유형인지 알 필요없이 여러 유형의 객체를 포함하는 배열을 가질 수 있다는 것입니다. 나는 최근에 이것을 사용하여 각각 별도의 방법으로 I2C 장치를 나타내는 객체 배열을 갖습니다.

주로 소규모 시스템에서는 허용되지 않는 런타임 오버 헤드로 인해 사용하지 않는 영역 :

  • 동적 메모리 할당-다른 사람들이 이것을 언급했지만 동적 메모리 할당을 사용 하지 않는 또 다른 중요한 이유 는 타이밍의 불확실성을 나타냅니다. 임베디드 시스템을 사용해야하는 많은 이유는 실시간 애플리케이션을위한 것입니다.
  • RTTI (런타임 유형 정보)-메모리 비용이 다소 큼
  • 예외- 실행 속도 적중으로 인한 명확한 아니오

입력 해 주셔서 감사합니다. 흥미롭고 내가 읽은 것과 매우 비슷합니다.
Kortuk

1
실제로 동적 메모리 할당은 좋으며 때로는 피할 수 없습니다. 문제가되는 것은 동적 메모리 할당 해제 (및 후속 재사용)입니다. RTTI는 메모리 호그입니다. 그러나 예외의 문제점은 무엇입니까?
Wouter van Ooijen

1
@WoutervanOoijen : 예외의 문제 는 / 블록 내에서 foo호출 하고 일부 객체와 호출을 생성 하여 예외를 발생시키는 경우 시스템은 제어를에 반환하기 전에 생성 된 객체에 대해 소멸자를 호출해야 한다는 것 입니다. 예외가 완전히 비활성화되지 않는 한, 예외가 발생 하는지 알 수 있는 방법이 없으므로 해당 가능성을 허용하기 위해 추가 코드를 포함해야합니다. 이를 처리하기 위해 "체크 된 예외"가있는 C ++의 변형을보고 싶습니다. 예외를 피할 수있는 루틴이라면 ...bartrycatchbarbozbarfoobarboz
supercat

1
... 그러한 것으로 선언되어야한다면, 컴파일러는 그러한 루틴의 호출자에 예외 처리 코드를 포함시키기 만하면됩니다. 확실히, 불필요한 선언을 피하면서 필요한 모든 선언을 추가 해야하는 것은 다소 부담이 될 수 있지만 예외가 아닌 곳에 오버 헤드를 추가하지 않고 유용한 곳에서 예외를 사용할 수 있습니다.
supercat

3
@WoutervanOoijen : 우연히, ARM에서 이러한 예외 처리를 위해 ABI를 설계하는 경우 예외를 통해 종료 될 수있는 루틴을 호출하는 코드가 R14가 원하는 반환 주소 앞의 2 바이트 주소를 가리 키도록 지정합니다 (이것은 호출자가 16 비트 단어로 CALL 명령을 따랐을 경우 자연스럽게 발생합니다. 호출 된 루틴은 다음 add r15,r14,#2대신에 정상적으로 종료됩니다 mov r15,r14. 예외를 통해 종료하려면 ldrhs r0,[r14] / add r15,r14,r0. 정상 종료에 대한 사이클 비용이없고 스택 프레임 제한이 없습니다.
supercat

36

예, C ++은 임베디드 시스템에 적합합니다. 먼저 C와 C ++의 차이점에 대한 몇 가지 오해를 정리해 보겠습니다.

내장 마이크로에서는 시간이나 공간 제약이 우려되는 경우 항상 고급 언어를 신중하게 사용해야합니다. 예를 들어 많은 MCU가 포인터를 제대로 처리하지 않으므로 스택을 사용할 때 매우 비효율적입니다. 즉, 변수를 함수에 전달하고 배열과 포인터를 사용하고 재귀에주의해야합니다. C의 간단한 라인은 다음과 같습니다.

a[i] = b[j] * c[k];

변수의 특성에 따라 약 4 페이지의 명령어를 생성 할 수 있습니다.

사용중인 때마다 어떤 높은 수준의 언어를, 당신은 시간과 공간의 제약에 대한 우려, 당신은 방법을 알아야 매일 (적어도 당신이 사용하는 모든 기능을) 해당 언어의 기능이 MCU에 기계 명령어로 변환합니다. 이것은 C, C ++, Ada 모두에게 해당됩니다. 아마도 모든 언어에는 작은 MCU에서 효율적으로 번역되지 않는 기능이 포함되어있을 것입니다. 디스 어셈블리 목록을 항상 확인하여 컴파일러가 사소한 것에 대한 많은 양의 명령어를 생성하지 않도록하십시오.

C는 내장 MCU에 적합합니까? 예, 생성 된 코드를 주시하는 한.
C ++는 임베디드 MCU에 적합합니까? 예, 생성 된 코드를 주시하는 한.

8 비트 MCU에서도 C ++가 C보다 낫다고 생각하는 이유는 다음과 같습니다. C ++는 다음에 대한 향상된 지원을 제공합니다.

  • 데이터 숨기기
  • 강력한 타이핑 / 확인
  • 클래스를 사용한 다중 주변기기 투명도
  • 템플릿 (항상주의해서 사용하는 경우)
  • 초기화리스트
  • const

이러한 기능 중 어느 것도 C의 일반적인 기능보다 무겁지 않습니다.

최대 16 또는 32 비트 MCU로 이동할 때 C의 더 무거운 기능 (스택, 힙, 포인터, 어레이, printf 등)을 사용하는 것이 합리적입니다. 같은 방식으로 더 강력한 MCU가 적합 해집니다 C ++의 더 무거운 기능 (스택, 힙, 참조, STL, 새 / 삭제)을 사용합니다.

따라서 PIC16에서 C ++에 대해 생각할 필요가 없습니다. 자신의 언어와 MCU를 제대로 알고 있다면, 두 언어를 효과적으로 함께 사용하는 방법을 알게 될 것입니다.


3
이것은 질문에 대한 잘 표현되고 합리적인 답변입니다. 건배 +1
vicatcu

1
" a[i] = b[j] * c[k];변수의 특성에 따라 약 4 페이지의 명령어를 생성 할 수 있습니다." MCU / 컴파일러가이 작업을 수행하는 경우 80 년대의 일부 차고 애호가 CPU를 사용하고 있기 때문입니다.
Lundin

@ 룬딘-한숨. 아니요, 스택 인덱싱과 같은 복잡한 것을 피하기 위해 가능한 작고 저렴하게 설계된 저렴한 소형 MCU를 사용하고 있음을 의미합니다.
Rocketmagnet 2016 년

2
@Rocketmagnet 좋아 1990 년대에? 요즘 비열한 8 개의 쓴 맛은 32 개의 쓴 맛과 같은 가격으로 제공됩니다. 전자를 고른 이유는 현재 소비입니다. 그리고 스택이없는 여분의 8 비트 쓰라린과 관련하여 : 제한된 MCU에 대해 어셈블러 대신 C를 작성하면 잘못되었을 수 있습니다. 생성 된 4 페이지는 CPU에 대해 너무 복잡한 프로그램을 작성하는 데있어 사용자 자신의 잘못이며 본질적으로 C는 작업에 대한 잘못된 도구입니다. (나는 과거에 Freescale RS08에서이 작업을 수행했습니다. 매우 어리석은 생각이었습니다.)
Lundin

@Lundin 32 비트 프로세서는 16 비트보다 빠를 필요가 없습니다. 이것은 PC 세계에서 16에서 32 비트로의 프로그램 전환이 진행되고 있던 당시에 분명한 방법이었습니다.
보리 맨

24

나는 항상이 토론이 재미있는 것을 발견합니다. 사용 가능한 다양한 언어의 장단점에 대한 지적 토론은 그리 많지 않지만 일반적으로 자신의 직업 / 경험 / 관심 분야에 따라 주제에 대한 누군가의 입장을 찌를 수 있기 때문입니다. CS 조기 전공과 유지 보수 프로그래머들이 Knuth를 좌우로 인용하고 성능 문제가 모두 미쳤다고 생각하는 실제 세계에서 일하는 사람들은 "조기 최적화"라는 주장과 함께 바로 거기에 있습니다 (후자 그룹의 구성원입니다) 공정하게).

하루가 끝나면 C 또는 C ++로 우수한 소프트웨어를 개발하거나 여기에 언어를 삽입 할 수 있습니다 . 언어가 아닌 개발자의 능력에 달려 있습니다. 언어 전문가가 되려면 일반적으로 잘못된 언어를 선택하여 문제를 해결하기 위해 언어를 변형해야하는 경우에만 필요합니다. 대부분의 경우 이러한 기능은 모호한 기능이나 컴파일러로 뛰어 들어야하는 유일한 상황입니다 목표를 달성하기위한 속임수.

나는 사람들이 이러한 주장을 "언어 X와 블라 블라 (Blah Blah)의 전문가"라고 시작하는 것을 종종 듣는다. 내 의견으로는, 그들은 이미 잘못된 각도에서 문제에 접근했고 그 이후의 모든 것이 오염 되었기 때문에 솔직히이 사람들을 불신한다. 도구를 사용하여 문제를 해결하고 얼마나 '멋진'지를 보여주기를 원합니다.

나는 종종 개발자들이 도구 세트를 먼저 선택하고 문제를 두 번째로 구부리려고 시도하는 것을 보았습니다.

다른 답변에 대한 언급에서 언급했듯이, 이러한 언어 전쟁은 종종 언어 X가 프로그래머가 더 멍청한 일을 할 수 있다고 주장합니다. 읽는 것이 즐겁지만, 이러한 모든 진술은 실제로 훌륭한 개발자를 고용하는 데 문제가 있고 나쁜 개발자를 계속 고용하고 상황이 작은 개발자가 할 수있는 도구를 선택하여 상황을 돕지 않고 직접 문제를 해결해야한다는 것을 의미합니다 가능한 피해.

제 생각에는 소프트웨어 나 하드웨어 개발, 문제 조사, 솔루션 설계, 솔루션을 '최고의 방법으로'표현할 수있는 도구를 찾는 좋은 개발자입니다. 새로운 도구를 선택하는 프로젝트에 3-4 개 언어 / 개발 도구를 사용한 후에는 필요한 도구가 이전에 사용해 본 적이없는 도구인지 여부는 중요하지 않습니다. 개발 시간에 최소한의 영향을 미칩니다.

물론 '최상의 방법'은 주관적인 용어이며 연구 단계에서 정의해야합니다. 성능, 표현의 용이성, 코드 밀도 등과 같은 여러 가지 문제를 고려해야합니다. 적절한 이유로 도구를 선택하고 이것이 '무료'라는 문제를 이해하는 데 시간을 들인 경우, 선택한 언어에 상관없이 목록에 유지 관리 기능을 포함시키지 않았습니다. 코드를 유지하기 어려운 것은 종종 잘못된 도구 나 열악한 시스템 구조를 선택한 결과이며, 이로 인해 코드가 제대로 작동하지 않는 경우가 있습니다.

어떤 언어가 다른 언어보다 '더 나은'것이라고 주장하는 것은 관심있는 특정 문제를 정의하지 않고 어리석은 일입니다. 객체 지향 접근법이 항상 기능적 접근법보다 낫지는 않습니다. 객체 지향 디자인 패러다임에 매우 적합한 몇 가지 문제가 있습니다. 그렇지 않은 많은 사람들이 있습니다. 사람들이 좋아하는 많은 언어 기능에 대해서도 같은 말을 할 수 있습니다.

실제로 코드를 입력하는 문제에 시간의 20 % 이상을 소비하는 경우 시스템 성능이 매우 좋지 않거나 개발자가 매우 열악한 것입니다 (또는 여전히 배우고 있음). 문제의 다이어그램을 작성하고 다양한 응용 프로그램이 상호 작용하는 방식을 결정하는 데 대부분의 시간을 투자해야합니다. 마커 보드와 문제를 해결하기 위해 문제가있는 방에 재능있는 개발자 그룹을 고수하고 전체 시스템에 익숙해지기 전에는 코드를 작성하거나 도구를 선택할 수 없습니다. 개발 시간을 단축 할 수있는 새로운 도구를 선택하는 것보다 출력 및 개발 속도가 빠릅니다. (내 주장과 반대되는 극점에 대한 참조로 스크럼 개발을 찾아보십시오)

불행히도 현실은 많은 기업들이 작성된 줄 수 또는 '유형 산출물'로만 개발자의 가치를 측정 할 수 있다는 것입니다. 그들은 마커 보드가있는 방에서 3 주를 생산성 손실로 봅니다. 개발자들은 종종 '생각'개발 단계를 거쳐야하거나 회사 내 정치적 문제에 의해 설정된 도구를 사용하도록 강요받습니다. "내 상사의 형제는 IBM을 위해 일하기 때문에 도구 만 사용할 수 있습니다." . 더 나쁜 것은 적절한 시장 조사를 할 수 없거나 개발주기에 대한 변경의 영향을 이해하지 못하기 때문에 회사에서 끊임없이 변화하는 요구 사항을 얻는 것입니다.

이 폭언으로 주제를 벗어난 것에 대해 유감스럽게 생각합니다. 저는이 주제에 대해 매우 강한 의견을 가지고 있습니다.


2
이제 특정 임베디드 시스템의 응용 프로그램 수준 (드라이버 위)에서 단위 테스트를 수행하지 않습니다. 개발 단계 초기에 단위 테스트와 버그 근절에 대한 즉각적인 피드백의 가치가 있지만 디자인을 낳는 전체 TDD 패러다임은 나에게 약간의 뇌사처럼 보입니다. 코드를 시작하기 전에 문제에 대해 "생각"하고 머리, 종이 또는 화이트 보드에 시간을내는 것을 선호합니다. 또한 TDD는 시장이 요구 사항에 대한 선행 연구를하지 않는 것이 좋습니다. 그것이 요구 사항을 지속적으로 변경하는 데 도움이되기 때문입니다.
Jay Atkinson 2016 년

2
그리고 나의 긴 의견에 대한 최종 메모를 남기기 위해 .. 우리는 디자인 작업을 위해 언어 전문가가 필요하지 않습니다. 언어를 사용할 수있는 전문 디자이너가 필요합니다.
Jay Atkinson 2016 년

1
PRD = 제품 요구 사항 문서, MRD = 마케팅 요구 사항 문서, TRD = 기술 요구 사항 문서 TDD = 테스트 주도 개발.
Jay Atkinson 2016 년

1
@Mark-나는 당신의 디자인-정신 감정에 동의하지만, 한 지점에 한합니다. a) 귀하가 요구 사항이 상당히 안정 / 알고 있고 b) 디자인을 수행하는 개발자가 경험 이 있다면 무거운 디자인-업-프론트 작업이 도움이된다고 생각 합니다 . 이전 직업, 나는 디자인을하는 일을 맡았고 팀 리더가 엄중하게 타임 박스를 만들었고, "무엇을해야합니까! 그러나 코딩에서 나는 내가 알지 못하는 수많은 것들을 발견했습니다. 많은 디자인을하고 코드 시간을 최소화했다면 낭비 였을 것입니다. JME.
J. Polfer

1
@ sheepsimulator 저는 분명히 두 번째 요점에 동의합니다. 저는 수석 시스템 설계자가 숙련 된 개발자라고 생각합니다. 첫 번째 시점에서 나는 실제로 동의하지 않습니다. 좋은 변경하기 쉬운 디자인을 만들어야하기 때문에 요구 사항이 변경 될 것으로 예상할수록 디자인 단계에서 더 많은 시간을 소비해야한다고 생각합니다. 나는 어떤 철학이 빠른 발전을 제안한다는 것을 알고 있습니다. 어떤 경우에는 직원에 대한 많은 나쁘거나 경험이 부족한 프로그래머처럼 잘 작동합니다. 이 모든 디자인 철학은 "유연한 시스템을 설계 할기도가 없기 때문에 시간을 낭비하지 말라"고 말합니다.
Mark

17

모든 언어는 임베디드 시스템에 적합 할 수 있습니다. 임베디드는 단지 사용하기 쉬운 컴퓨터가 아니라 더 큰 장치의 일부를 의미합니다.

이 질문은 (실시간) 실시간 또는 제한된 자원 시스템을 요청할 때 더 관련성이 있습니다.

실시간 시스템의 경우 C ++은 엄격한 시간 제약 조건을 프로그래밍 할 때 여전히 적합한 최고 언어 중 하나입니다. 힙 사용 (무료 연산자)을 제외하고는 실행 시간이 확정되지 않은 구성 요소가 없으므로 프로그램이 타이밍 요구 사항을 충족하는지 여부를 테스트 할 수 있으며 경험이 더 있으면이를 예측할 수도 있습니다. 물론 새로운 연산자는 일회성 할당에 사용될 수 있지만 힙 사용은 피해야합니다. C ++가 C보다 제공하는 구성은 임베디드 시스템 (OO, 예외, 템플릿)에서 잘 활용할 수 있습니다.

리소스 제한이 매우 높은 시스템 (8 비트 칩, 몇 Kb 미만의 RAM, 충분한 스택 없음)의 경우 전체 C ++은 여전히 ​​'더 나은 C'로 사용될 수 있지만 적합하지 않을 수 있습니다.

나는 아이다가 일부 틈새 시장에서만 사용되는 것 같습니다. 여러 가지면에서 그것은 파스칼 ++이지만, 이미 시작하기에 이미 엉망인 언어와 호환되는 부담이 없습니다. (편집 : 심각한 혼란은 물론 C입니다. 파스칼은 아름답지만 다소 비현실적인 언어입니다.)

===================================================== ==============

편집 : 나는이 질문에 대해 폐쇄 된 새로운 질문 ( "어떤 경우에 우리가 마이크로 컨트롤러를 프로그래밍 할 때 C ++이 필요한가?")에 대한 답을 입력하고 있었으므로 내가 쓴 것을 추가 할 것입니다.

의 사용에 대한 모든-위압 이유가 결코 어떤 프로그래밍 언어, 특정 상황에서 더 많거나 적은 무게를 인수있을 수 있습니다. 이에 대한 논의는 "마이크로 컨트롤러에 C ++을 사용하지 마십시오"에서 "항상 C ++을 사용"하는 위치까지 다양한 위치에서 찾을 수 있습니다. 나는 마지막 위치에 더 있습니다. 나는 몇 가지 주장을 할 수는 있지만 특정 상황에서 (그리고 어느 방향으로) 얼마나 많은 무게를 지니고 있는지 스스로 결정해야합니다.

  • C ++ 컴파일러는 C 컴파일러보다 훨씬 드 rare니다. 일부 대상 (예 : 12 및 14 비트 코어 PIC)의 경우 C ++ 컴파일러가 전혀 없습니다.
  • (좋은) C ++ 프로그래머는 (좋은) C 프로그래머보다 더 드물며, 특히 전자 기술에 대해 잘 알고있는 사람들 중에서도 더 드 rare니다.
  • C ++은 C보다 작은 시스템에 적합하지 않은 더 많은 구문을 가지고 있습니다 (예외, RTTI, 자주 힙 사용).
  • C ++는 C보다 풍부한 표준 라이브러리를 가지고 있지만, 이전의 결과는 C ++ 라이브러리가 종종 소규모 시스템에는 부적합한 기능을 사용하므로 소규모 시스템에서는 사용할 수없는 기능입니다.
  • C ++는 C보다 더 많은 구성을 가지고있어 발로 스스로를 쏠 수 있습니다.
  • C ++에는 C보다 더 많은 구문이 있어 발로 자신을 쏘지 못하게 할 수 있습니다 (예, IMO와 이전의 IMO 모두 가능)
  • C ++에는 풍부한 추상화 메커니즘이 있으므로 특히 라이브러리에 대해 더 나은 프로그래밍 방법을 사용할 수 있습니다.
  • C ++ 언어 기능 (예 : 생성자 / 소멸자, 변환 함수)으로 인해 코드를 통해 생성 된 기계를 확인하기가 어려우므로 언어 ​​구성의 공간 및 시간에 따른 비용이 발생합니다.
  • C ++ 언어 구조는 좀 더 추상적 인 방식으로 '올바른 것'을 수행하기 때문에 어떻게 정확하게 기계 코드로 변환되는지 알 필요가 없습니다.
  • C ++ 언어 표준은 빠르게 발전하고 있으며 대형 컴파일러 (gcc, clang, microsoft)에서 빠르게 채택하고 있습니다. C는 다소 격렬하게 발전하고 있으며 일부 새로운 기능 (변형 배열)의 채택은 겁이 나고 나중에 표준으로 되돌아 왔습니다. 이 점은 특히 다른 사람들이 반대 위치를 지원하기 위해 사용한다는 점에서 흥미 롭습니다.
  • C ++는 의심 할 여지없이 C보다 더 날카로운 도구입니다. 프로그래머 (또는 자신)가 그러한 도구를 사용하여 아름다운 조각을 만들거나 자신을 다치게하는 것을 두려워하고 덜 아름답지만 위험이 적은 제품에 정착하겠습니까? ? (조각 선생님이 무딘 도구가 어떤 상황 에서는 날카로운 도구 보다 위험 할 수 있다고 말한 적이 있습니다.)

블로그 에는 소형 시스템 (= 마이크로 컨트롤러)에서 C ++ 사용에 대한 글이 있습니다.


15

내 경험상 C ++은 일반적으로 소형 임베디드 시스템에는 적합하지 않습니다. 즉, 마이크로 컨트롤러 및 OS없는 장치입니다.

많은 C ++ OOP 기술은 동적 메모리 할당에 의존합니다. 소규모 시스템에서는 종종 누락됩니다.

STL과 Boost는 실제로 C ++의 힘을 보여줍니다.

C ++은 프로그래머가 기계를 추상화하여 제약 된 시스템에서 수용해야한다고 권장합니다.

작년에 상용 원격 데스크톱 제품을 휴대 전화로 이식했습니다. C ++로 작성되었으며 Windows, Linux 및 OSX에서 실행되었습니다. 그러나 STL, 동적 메모리 및 C ++ 예외에 크게 의존했습니다. WinCE, Symbian 및 OS없는 환경에서 C 재 작성이 가장 좋은 옵션이었습니다.


소규모 시스템에 대해서는 동의하지만 소규모 시스템에 대해 다른 정의가 있다고 생각합니다. 1kB의 ROM이 있고 잘 작성된 C 코드가 1 바이트의 ROM을 모두 차지하면 작은 시스템입니다.
Kortuk

6
나는 C가 더 작은 풋 프린트를 가질 수 없다고 주장하지는 않지만 C ++을 여전히 사용할 수 있었고 방금 논의한 것에 대한 디자인과 매우 유사한 결과를 얻었습니다. 문제는 대부분의 OOP 프로그래머가 동적 메모리가 있고 매우 비효율적 인 구성을 사용하여 저전력 시스템에 완전히 쓸모없는 코드를 생성하는 시스템에 사용된다는 것입니다.
Kortuk

4
그래서 당신이 말하는 것은 C ++을 사용하고 싶지 않다는 것입니다 .C와 C ++ 사이에 무언가를 사용하고 싶습니다 (C +라고 부릅니까?). 이 경우 동의합니다 .C ++ 사람들에게는 많은 것이 쓸모없고 사용 가능한 것이기 때문에 최적이 아닙니다. 거의 모든 언어는 사용 방법에 관계없이 훌륭하고 빠른 코드를 생성 할 수 있습니다. 언어에 대한 대부분의 거룩한 전쟁은 언어 능력의 결과가 아니라 바보가 바보 같은 일을하는 것이 얼마나 쉬운 지에 대한 논쟁입니다. 이것은 바보 같은 논쟁입니다 : p
Mark

2
"언어에 대한 대부분의 거룩한 전쟁은 언어 능력의 결과가 아니라 바보가 바보 같은 일을하는 것이 얼마나 쉬운가에 대한 논쟁이다. 이것은 정말 바보 같은 논쟁이다." 매우 즐거운 문장이었습니다. 성을 인용 할 수 있도록 성이 필요합니다.
Kortuk

1
그래도 C에서 동적 메모리를 사용하지 않습니다. 내가 가질 필요가 없습니다. 장기적으로는 매우 세분화되어 문제를 일으킬 수 있다는 것을 읽었습니다. 메모리 부족을 위해 매우 명확하게 디자인 된 사례가 있어야하며, 남은 양을 정확히 모니터링 할 수 있어야합니다.
Kortuk

11

베어 메탈 및 리소스 제한 시스템의 C ++에 대한이 토론에 열보다 많은 빛을 추가하고 싶습니다.

C ++의 문제점 :

  • 필요한 "비상 버퍼"(예를 들어, 메모리 부족 예외가 발생하는 경우)가 사용 가능한 RAM보다 클 수 있고 마이크로 컨트롤러의 낭비 일 수 있으므로 예외는 특히 RAM 문제입니다. 자세한 정보는 n4049n4234를 참조하십시오 . 꺼야합니다 (현재 지정되지 않은 동작이므로 반드시 버리지 마십시오). SG14는 현재 더 나은 방법으로 작업하고 있습니다.

  • RTTI는 아마도 오버 헤드 가치가 없을 것입니다.

  • 대형 디버그 빌드. 클래식 데스크톱 개발에서는 문제가되지 않지만 디버그가 칩에 맞지 않으면 문제가 될 수 있습니다. 문제는 명확성을 위해 템플릿 코드 또는 추가 함수 호출에서 발생합니다. 이러한 추가 함수 호출은 옵티 마이저에 의해 다시 제거되며 추가 된 명확성 또는 유연성은 큰 이점이 될 수 있지만 디버그 빌드에서는 문제가 될 수 있습니다.

  • 힙 할당. STL은 사용자 지정 할당자를 사용할 수 있지만 대부분의 프로그래머에게는 복잡 할 수 있습니다. 힙 할당은 결정적이지 않으며 (즉, 하드 실시간이 아님) 조각화는 테스트 작업에도 불구하고 예기치 않은 메모리 부족 상황이 발생할 수 있습니다. 여유 공간과 다양한 크기를 추적하기 위해 힙에 필요한 책 보관은 작은 개체에 문제가 될 수 있습니다. 일반적으로 풀 할당 (C 및 C ++ 모두)을 사용하는 것이 좋지만 힙만 사용하는 C ++ 프로그래머에게는 비정상 일 수 있습니다.

  • 런타임 다형성 및 기타 간접 호출은 일반적으로 성능에 큰 영향을 미칩니다. 옵티마이 저가 실제 페치 및 주소로 점프하는 것 이상으로 볼 수 없기 때문에 문제가 더 많습니다. 이러한 이유로 C 및 C ++에서는 간접 호출을 피해야합니다. C ++에서와 같이 문화에 더 깊이 뿌리 박고 있으며 다른 도메인에서는 매우 유용합니다.

  • clib와의 암시 적 인터페이스는 문제가 될 수 있습니다. clib 문제가 C ++ 범주에 있다는 것은 직관적이지 않을 수 있지만 동시 환경에서 자원을 암시 적으로 공유하면 문제가 발생합니다 (C에서는 공유가 더 명확합니다). 일반적인 newLib 구현의 사용은 종종 uC에서는 일반적으로 필요하지 않은 많은 부풀어 오름을 초래합니다. 반면에 newLibNanno는 재진입 할 ​​수 없으므로 액세스가 직렬화되어야합니다 (여기에서는 단순화). 이것은 C의 문제이기도하지만 액세스가 더 명시 적입니다. 경험상 clib의 상태에 어떤 식 으로든 액세스하지 않는 경우 (예 : 오류 또는 힙) ISR 컨텍스트의 네임 스페이스 std에서 아무것도 사용하지 않아야합니다. malloc과 free에 대한 액세스를 동기화하기 위해 스레드를 사용하여 새 것을 무시하고 삭제하는 것이 중요합니다 (RTC를 선호합니다).

결론적으로 C ++에는 몇 가지 문제가 있지만 본질적으로 모두 고칠 수 있거나 피할 수 있습니다.

이제 C의 경우 문제는 더 높은 차수입니다. C에서 컴파일 타임에 최적화를 수행하거나 불변을 확인할 수있는 방식으로 사물을 추상화 할 수있는 구문 능력이 없습니다. 따라서 사용자가 사용 방법을 알 필요가없는 방식으로 물건을 올바르게 캡슐화 할 수 없으며 대부분의 오류 감지는 런타임에 수행됩니다 (너무 늦을뿐만 아니라 비용이 추가됩니다). 본질적으로 C에서 일반화하는 유일한 방법은 데이터를 통하는 것입니다. 예를 들어 런타임에 평가되는 형식 문자열을 printf 또는 scanf에 전달합니다. 컴파일러가 올바른 데드 코드를 전달할 때 이론적으로 가능한 옵션 중 일부를 사용하지 않는다는 것을 증명하는 것은 매우 어렵습니다. 이는 잠재적 인 데드 코드 생성 및 최적화 가능성의 손실을 의미합니다.

나는 여기서 똥 폭풍을 풀고 있지만 32 비트 마이크로 컨트롤러에 대한 나의 경험은 사과와 사과에서 C와 C ++을 전문가가 작성한 C와 C ++ 비교 (C ++ 가능성이 높은 템플릿에서와 같이) C ++이 최대한 효율적인 언어라는 것입니다 라이브러리와 마찬가지로 모든 것이 일반적이어야하며 일반적이지 않은 경우와 동일합니다. 초보자도 C ++에서 전문 라이브러리 구현 자의 전문 지식을 활용하는 것이 더 쉽습니다.

동시에 입력이 int가 아니지만 somethingint를 표현 방법으로 사용하는 즉시 잘못된 데이터를 전달할 수없는 함수가 실제로 거의 없습니다. 잘못되었습니다 ( '무언가'가 아닌 잘못된 값이나 'otherThing'을 전달하십시오). C에서 사용자가 잘못했는지 확인하는 유일한 방법은 런타임입니다. C ++에서는 모든 검사가 아니라 컴파일 타임에 일부 검사가 무료 인 검사를 수행 할 수 있습니다.

하루가 끝나면 C 팀은 가장 약한 프로그래머만큼 강력하며 결과 코드의 이점은 멀티 플레이 1 또는 성능 저하입니다. 이것이 의미하는 바는 독특한 디자인 결정의 독특한 환경에서 하나의 유일한 작업에 대한 고성능이거나 여러 환경 (다른 마이크로 컨트롤러, 다른 메모리 관리 전략, 다른 대기 시간 vs. 처리량 트레이드 오프 등)이지만 고유 한 성능 비용이 있습니다.

C ++에서는 사물을 전문가가 캡슐화 할 수 있으며 컴파일 타임 코드 생성이 특정 작업에 적응하고 정적 검사를 통해 사용자가 비용없이 바보 같은 일을 수행하지 못하게하는 많은 환경에서 사용될 수 있습니다. 여기서 우리는 일반적인 것과 빠른 것 사이의 거래가 훨씬 적으므로 궁극적으로 비용 대 이익 관점에서 더 성능적이고 안전하며 생산적인 언어입니다.

임베디드 용으로 좋은 C ++ 라이브러리가 여전히 부족하다는 사실은 유효한 비판이며, 이는 C ++ 컴파일러에서 C를 주로 사용하는 실용적인 결정으로 이어질 수 있습니다. 프로젝트에서 C 만 사용하기로 한 결정은 근본적으로 이념적으로, 레거시 지원이 필요하지 않거나 팀이 C ++에서는 할 수 있지만 C에서는 할 수없는 엄청나게 바보 같은 일을 자제 할만큼 훈련을받지 않았다는 인정 동시에 C에서는 보호 할 수 없지만 C ++에서는 할 수없는 훨씬 더 어리석은 일을하지 않도록 충분히 훈련을 받았습니다.


내 대답에 좋은 추가 :)이 신비로운 C ++ 애호가는 누구입니까? 그의 프로필은 "분명히,이 사용자들은 그들에 대해 미스터리를 유지하는 것을 선호한다"고 말합니다. (나쁜 영어, BTW) BUT AHA 위치는 "Bochum, Germany"입니다 ..... 회의에서!겠습니다!
Wouter van Ooijen

아 그래, 내 프로필을 업데이트;) 당신이 emBO ++에 오는 것을 알고 좋은 그것은 좋은 군중이 될 것입니다
odinthenerd

10

저의 배경 : 오래된 Bell Labs 프로그래머들의 학교 밖에서의 훈련; 저학년 연구 프로젝트에서 2 년 동안 3 년간 일하고 있습니다. VB.NET의 데이터 수집 / 프로세스 제어. VB6의 엔터프라이즈 데이터베이스 애플리케이션에서 1.5 년 동안 일했습니다. 현재 2GB 스토리지, 512MB RAM, 500MHz x86 CPU가 내장 된 임베디드 PC 용 프로젝트를 진행 중입니다 . IPC 메커니즘을 사용하여 C ++로 동시에 작성된 여러 앱. 예, 저는 어립니다.

내 의견 : 위에서 작성한 환경을 고려할 때 C ++이 효과적으로 작동 할 수 있다고 생각 합니다. 분명히, 실제 실시간 성능은 내가 사용하는 앱과 일부 내장 응용 프로그램의 요구 사항이 아니므로 문제가 될 수 있습니다. 그러나 내가 배운 것들은 다음과 같습니다.

  • C ++는 기본적으로 C와 다릅니다 (즉, C / C ++가 없습니다). 유효한 C 인 모든 것이 유효한 C ++ 인 반면, C ++은 매우 다른 언어이며 어떤 상황 에서도 효과적으로 사용하기 위해 C가 아닌 C ++로 프로그래밍하는 방법을 배워야합니다 . C ++에서는 두 가지 (많은 함수를 가진 큰 클래스)의 하이브리드가 아니라 절차 지향적이 아닌 객체 지향적으로 프로그래밍해야합니다. 일반적으로 함수가 거의없는 작은 클래스를 만드는 데 중점을두고 모든 작은 클래스를 더 큰 솔루션으로 구성해야합니다. 동료 중 한 명이 객체로 절차 적으로 프로그래밍하는 데 사용했다고 설명했습니다. 이는 엉망이고 유지하기가 어렵습니다. 더 많은 객체 지향 기술을 적용하기 시작했을 때 코드의 유지 관리 성 / 가독성이 향상되었음을 알았습니다.

  • C ++는 객체 지향 개발 형태로 추가 기능을 제공 하여 코드를보다 쉽게 ​​읽고 유지 관리 할 수 있는 방법을 제공 합니다 . 솔직히 말해서, OOP를 수행함에있어 성능 / 공간 효율 개선 방법이 많이 없다고 생각합니다. 그러나 OOP는 복잡한 문제를 많은 작은 조각으로 나눌 수있는 기술이라고 생각합니다. 그리고 이것은 코드를 작업하는 사람들에게 도움이됩니다.이 과정에서 무시해서는 안되는 요소입니다.

  • C ++에 대한 많은 주장은 주로 동적 메모리 할당과 관련이 있습니다. C도 같은 문제가 있습니다. 동적 메모리를 사용하지 않고도 객체 지향 응용 프로그램을 작성할 수 있지만 객체를 사용하면 얻을 수있는 이점 중 하나는 이러한 방식을 쉽게 동적으로 할당 할 수 있다는 것입니다. C에서와 마찬가지로 메모리 누수를 줄이기 위해 데이터를 관리하는 방법에주의해야하지만 RAII 기술 은이를 C ++에서 더 단순하게 만듭니다 (객체에 데이터를 캡슐화하여 동적 메모리를 자동으로 소멸시킵니다). 모든 메모리 위치가 중요한 일부 응용 프로그램에서는 관리하기에 너무 거칠고 울퉁불퉁 할 수 있습니다.

편집하다:

  • WRT "Arduino C ++"질문 : 동적 메모리 관리가없는 C ++가 여전히 유용 할 수 있다고 주장합니다. 코드를 객체로 구성한 다음 해당 객체를 애플리케이션 내 다양한 ​​위치에 배치하거나 콜백 인터페이스를 설정하는 등의 작업을 수행 할 수 있습니다. 이제 C ++로 개발하고 있으므로 애플리케이션에 모든 데이터가 할당 된 여러 가지 방법을 볼 수 있습니다. 스택은 여전히 ​​객체에 유용 할 수 있습니다. 그래도 인정할 것입니다-실제로 Arduino와 같은 임베디드 앱을 작성하지 않았으므로 주장에 대한 증거가 없습니다. 다가오는 프로젝트에서 Arduino 개발을 할 수있는 기회가 있습니다.

2
두 번째 요점에 대해 언급하고 싶습니다. 복잡한 문제를 많은 작은 조각으로 나누는 데 도움이되며 그 기능을 무시해야한다고 말합니다. 이것이 내가 프로 C ++ 인 정확한 이유입니다. 프로그래밍에 대한 매우 많은 연구 결과에 따르면 프로그램 크기가 선형으로 증가하면 개발 시간이 기하 급수적으로 증가합니다. 프로그램을 올바르게 분할 할 수 있다면 개발 시간이 기하 급수적으로 감소 할 수 있습니다. 이것은 지금까지 가장 중요한 것입니다.
Kortuk

두 번째 요점도 : OOP 설계 방법을 사용하면 더 구획화 된 코드가 생성되지 않습니다. 좋은 기본 디자인을 가지고 있다면, 그 디자인을 표현하는 방법은 개발자에게 있습니다. OOP는 코드를 올바르게 분리한다고 정의하지 않고 다른 옵션을 제공하며 외형은 그 이상이지만 외관상으로는 좋은 디자인을 강요하지는 않으며 개발자에게 달려 있습니다.
Mark

항상 그렇습니다. 좋은 디자인을 강요하는 언어에 대해 들어 본 적이 없습니다. 필자는 개발자의 직무이며 C ++을 사용하여 체계적인 방식으로 사용하고 구현하기가 쉽다고 생각합니다.
Kortuk

@Mark-동의합니다. 그것은 나를위한 학습 과정이었습니다.
J. Polfer

7

그렇습니다. C ++의 문제는 코드의 발자국 증가입니다.

일부 시스템에서는 바이트 수를 계산하는 경우 시스템 경계에 근접한 실행 비용이 C의 개발 비용 증가에 해당하는 운영 비용을 수용해야합니다.

그러나 C에서도 잘 설계된 시스템의 경우 모든 것을 캡슐화해야합니다. 잘 설계된 시스템은 어렵고 C ++은 프로그래머에게 매우 체계적이고 통제 된 개발 방법을 제공합니다. OOP를 배우는 데 비용이 들며,이를 전환하려면 많은 동의를해야하며, 대부분의 경우 관리는 C로 계속 진행하고 비용을 지불하지 않을 것입니다. 스위치의 결과를 측정하기가 어렵 기 때문입니다. 생산성을 향상시킵니다. 임베디드 시스템 전문가 인 Jack Ganssle 의 기사를 여기서 볼 수 있습니다 .

동적 메모리 관리는 악마입니다. 실제로, 악마는 자동 경로 지정이 아니며 동적 메모리 관리는 PC에서 훌륭하게 작동하지만 최소한 몇 주마다 PC를 다시 시작할 것으로 기대할 수 있습니다. 임베디드 시스템이 5 년 동안 계속 작동함에 따라 동적 메모리 관리가 실제로 망쳐 져 실제로 실패하기 시작할 수 있습니다. Ganssle은 그의 기사에서 스택 및 힙과 같은 것을 논의합니다.

C ++에는 문제를 일으키기 쉽고 많은 리소스를 사용하는 경향이있는 것들이 있습니다. 동적 메모리 관리를 제거하고 템플릿은 C ++의 풋 프린트를 C의 풋 프린트에 가깝게 유지하는 큰 단계입니다. 여전히 C ++이므로 동적이 필요하지 않습니다. 좋은 C ++를 작성하기위한 메모리 관리 또는 템플릿. 나는 그들이 예외를 제거한다는 것을 몰랐다. 나는 예외를 릴리스에서 제거하는 코드의 중요한 부분으로 생각하지만 그 시점까지 사용한다. 현장 테스트에서 예외가 포착되고 있음을 알려주는 메시지를 생성하도록 예외를 가질 수 있습니다.


1
필자는 코드 풋 프린트가 문제라는 데 동의했지만 최근 플래시 크기가 마이크로 컨트롤러 가격, RAM 크기 또는 IO 핀 수보다 훨씬 적은 영향을 미치는 것으로 보인다.
Wouter van Ooijen

동적 메모리에 대한 논쟁은 더 중요한 IMO입니다. 나는 몇 주 동안 논스톱으로 실행할 수있는 산업 시스템을 보았지만 진단 계층 (C ++로 작성)은 다시 시작하는 시간을 약 12 ​​시간으로 제한 할 것입니다.
Dmitry Grigoryev 2016 년

6

나는 생각 이 안티 C ++ 호언 장담 리누스 토발즈 (Linus Torvalds)에 의해이 흥미로웠다.

C ++의 최악의 기능 중 하나는 상황에 따라 많은 것을 만드는 것입니다. 즉, 코드를 볼 때 로컬 뷰는 상황을 알기에 충분한 컨텍스트를 거의 제공하지 않습니다.

그는 임베디드 시스템 세계가 아니라 Linux 커널 개발에 대해 이야기하고 있습니다. 나에게 관련성은 이것에서 비롯됩니다 : C ++은 더 큰 컨텍스트를 이해해야하며 일련의 객체 템플릿을 사용하는 법을 배울 수 있습니다. 몇 달 안에 코드를 업데이트해야 할 때 템플릿을 기억할 것을 믿지 않습니다.

(반면에, 나는 현재 그 문제를 겪을 파이썬 (C ++이 아니라 동일한 OOP 패러다임을 사용하는)을 사용하는 임베디드 장치에서 작업하고 있습니다. 내 방어에서는 PC라고 할 정도로 강력한 임베디드 시스템입니다 10 년 전)


5
우리는 다를 수 있지만 프로젝트를 열면 즉시 무슨 일이 일어나고 있는지 알 수 없지만 C에서 잘 코딩 된 것과 C ++로 코딩 된 것이 있으면 C ++이 항상 더 좋아 보입니다. 명확한. C에서 개발을 잘하려면 C ++로 캡슐화를 구현해야합니다. 클래스를 올바르게 사용하면 인터페이스의 위치를 ​​명확하게 알 수 있으며 객체를 통해 완전히 처리 할 수 ​​있습니다.
Kortuk

캡슐화와 클래스에 완전히 동의했습니다. 연산자 오버로드와 상속은 그리 많지 않습니다.
pingswept June

1
하하, 네, 연산자 오버로딩은 코드의 기능을 난독 화하는 데 사용될 수 있습니다. 누군가 과부하가 걸리면 분명한 이유가 있거나 전혀하지 않아야합니다. 상속은 실제로 몇 가지 추가 사항이있는 부모와 같은 일을하는 특정 경우에만 사용해야합니다. 나는 OOP에서 모든 기능을 모두 사용하지는 않을 것이라고 생각합니다. 나는 두 가지를 모두 사용했지만 임베디드 시스템에서는 내가 그럴 것이라고 생각할 수 없습니다. 변수 이름에 80 자 제한이있는 컴파일러는 즉시 폐기해야한다고 생각합니다.
Kortuk

2
방금 파이썬으로 MCU를 프로그래밍한다는 생각에 약간의 입을 던졌습니다.
vicatcu

당신은 유일한 사람은 아니지만 그것이 잘 작동하고 효율적이라면, 나는 용서할 수 있습니다.
Kortuk

6

다른 답변이 장단점과 의사 결정 요인에 대해 꽤 좋은 사례라고 생각합니다. 따라서 몇 가지 의견을 요약하고 추가하고 싶습니다.

소형 마이크로 컨트롤러 (8 비트)의 경우에는 없습니다. 당신은 자신을 다치게 요구하고 있습니다. 이득이 없으며 너무 많은 자원을 포기할 것입니다.

괜찮은 OS를 가진 하이 엔드 마이크로 컨트롤러 (예 : RAM 및 스토리지의 경우 32 비트, 10 또는 100MB)의 경우 완벽하게 작동하며 권장 할만한 제품입니다.

문제는 경계가 어디입니까?

확실하지는 않지만 C ++에서 1MB RAM 및 1MB 저장 공간을 갖춘 16 비트 uC 용 시스템을 개발 한 후에는 나중에 유감스럽게 생각합니다. 예, 효과가 있었지만 추가 작업은 그만한 가치가 없었습니다. 나는 예외와 같은 것들이 누수를 일으키지 않도록해야했습니다 (OS + RTL 지원은 버그가 많고 신뢰할 수 없었습니다). 또한 OO 앱은 일반적으로 많은 작은 할당을 수행하며 힙 오버 헤드는 또 다른 악몽이었습니다.

이러한 경험을 바탕으로 향후 프로젝트에서는 최소 16 비트, RAM 및 스토리지 용으로 최소 16MB의 시스템에서만 C ++을 선택한다고 가정합니다. 그것은 임의의 한계이며 응용 프로그램의 유형, 코딩 스타일 및 관용구 등에 따라 다를 수 있습니다. 그러나주의 사항을 감안할 때 비슷한 접근법을 권장합니다.


2
나는 여기에 동의하지 않아야한다. 시스템 리소스로 인해 C ++이 수용 될 수있는 갑작스런 지점이 아니며, 좋은 디자인 관행은 C의 발자국이있는 곳에 C ++의 발자국을 유지할 수 있습니다. 결과적으로 동일한 공간을 차지하는 OOP 디자인의 코드가 생성됩니다. 잘못 작성된 C는 마찬가지로 나쁠 수 있습니다.
Kortuk

1
글쎄, 그것은 응용 프로그램의 크기와 더 많은 공간을 필요로하는 특정 기능 (템플릿 및 예외와 같은)을 얼마나 많이 사용하는지에 달려 있습니다. 그러나 개인적으로 제한된 C ++로 제한 해야하는 것보다 오히려 C를 사용하고 싶습니다. 그러나 더 큰 RTL, 가상 메소드 썽크, 생성자 / 소멸자 체인 호출의 오버 헤드가 있습니다. 이러한 효과는 신중한 코딩으로 완화 될 수 있지만 C ++ 사용, 추상화 및 높은 수준의 관점.
fceconel

4

임베디드 시스템에 유용한 C ++의 일부 기능이 있습니다. 예외와 같이 비쌀 수 있으며 비용이 항상 명백하지 않을 수도있는 다른 것들도 있습니다.

만약 내가 진실을 알고 있다면, 두 세계의 장점을 모두 갖춘 인기있는 언어가있을 것이며 두 언어 모두에서 부족한 몇 가지 특징이 포함되었습니다. 일부 공급 업체에는 이러한 기능이 포함되어 있지만 표준은 없습니다. 보고 싶은 몇 가지 :

  1. 예외를 던지거나 누수 할 수있는 함수를 선언해야하는 Java와 같은 예외 처리. 이러한 선언에 대한 요구 사항은 프로그래밍 관점에서 다소 성가신 것이지만 함수가 성공하면 임의의 정수를 반환하지만 실패 할 수있는 경우 코드의 선명도를 향상시킵니다. 많은 플랫폼이 레지스터에서 리턴 값을 갖고 캐리 플래그에 성공 / 실패 표시를 가짐으로써 코드에서이를 저렴하게 처리 할 수 ​​있습니다.
  2. 정적 및 인라인 함수의 오버로드 만; 내 이해는 C의 표준 기관이 이름 맹 글링을 피하기 위해 함수 과부하를 피했다는 것입니다. 정적 및 인라인 함수의 오버로드를 허용하면 해당 문제를 피할 수 있으며 외부 함수 오버로드의 이점의 99.9 %를 얻을 수 있습니다 (.h 파일은 다른 이름의 외부 함수 측면에서 인라인 오버로드를 정의 할 수 있으므로)
  3. 임의 또는 특정 컴파일 시간 분석 가능 상수 매개 변수 값에 대한 과부하. 상수 값을 전달하면 일부 함수가 매우 효율적으로 인라인 될 수 있지만 변수를 전달하면 인라인이 매우 좋지 않습니다. 값이 일정하면 최적화 될 수있는 다른 시간 코드는 그렇지 않으면 비관 화 일 수 있습니다. 예를 들면 다음과 같습니다.
    인라인 void copy_uint32s (uint32_t * dest, const uint32_t * src, __is_const int n)
    {
      if (n <= 0) 반환;
      그렇지 않으면 (n == 1) {dest [0] = src [0];}
      그렇지 않으면 (n == 2) {dest [0] = src [0]; 대상 [1] = src [1];}
      그렇지 않으면 (n == 3) {dest [0] = src [0]; 대상 [1] = src [1]; 대상 [2] = src [2];}
      그렇지 않으면 (n == 4) {dest [0] = src [0]; 대상 [1] = src [1]; dest [2] = src [2]; 대상 [3] = src [3];}
      그렇지 않으면 memcpy ((void *) dest, (const void *) src, n * sizeof (* src));
    }
    
    컴파일 타임에 'n'을 평가할 수 있다면, 위 코드는 memcpy를 호출하는 것보다 효율적이지만, 'n'을 컴파일 타임에 평가할 수 없다면 생성 된 코드는 단순히 코드보다 훨씬 크고 느릴 것입니다. memcpy라고 불렀습니다.

나는 C ++의 아버지가 임베디드 전용 버전의 C ++에 너무 열중하지는 않지만 C를 사용하는 것보다 약간의 개선을 제공 할 수 있다고 생각합니다.

위와 같은 표준이 모든 유형의 표준에 고려되고 있는지 아는 사람이 있습니까?



@Joby Taffey : C ++ 제작자가 포함 된 하위 집합에 관심이 없다는 언급을 생략하기 위해 게시물을 편집 한 것 같습니다. 나는 노력이 있었다는 것을 알고 있지만, 내 이해로 그들은 그렇게 멀리 얻지 못했습니다. 나는 8 비트 프로세서를 사용할 수있는 표준화 된 언어를 확실히 사용할 것이라고 생각하며 위에서 설명한 것과 같은 기능은 모든 플랫폼에서 유용 할 것입니다. 위의 3 번 언어를 제공하는 언어에 대해 들어 보셨습니까? 매우 유용 해 보이지만 언어가 제공하는 것을 본 적이 없습니다.
supercat

"C ++의 아버지"는 임베디드 시스템 프로그래밍에 대한 경험이 전혀 없으므로 왜 그의 의견에 관심을 가져야합니까?
Lundin

@ 룬딘 (Lundin) : 일부 영향력있는 사람들이 다양한 문제에 대한 그의 의견에 관심을 갖고 있다는 사실은 다른 사람들이 그렇게하는 이유가 될 수 있습니다. 위의 글을 썼을 때 템플릿의 증가하는 힘은 컴파일 타임에 어떤 상수를 해결할 수 있는지에 따라 과부하를 가질 수있는 새로운 가능성을 추가했을 것이라고 생각합니다. 시간 기능 (내가 이해 한 바에 따르면, 다양한 것을 순서대로 시도하고 실패하지 않는 첫 번째 템플릿을 사용해야하는 템플릿을 지정합니다 ...
supercat

...하지만 컴파일러는 잠재적 인 대체물을 컴파일하는 데 상당한 노력을 낭비해야하며 결국 폐기 될 것입니다. "거의 시작"없이 "이것이 상수라면, 이렇게하십시오; 그렇지 않으면 이렇게하십시오"라고 더 깨끗하게 말할 수 있다면 더 깔끔한 접근 방법이 될 것입니다.
supercat

3

C ++은 하나 이상의 프로그래밍 언어입니다.

a) "더 나은"C입니다. b) 객체 지향 언어입니다. c) 일반적인 프로그램을 작성할 수있는 언어입니다.

이러한 기능을 모두 별도로 사용할 수 있지만 세 기능을 동시에 사용하면 최상의 결과를 얻을 수 있습니다. 그럼에도 불구하고 그 중 하나만 선택하면 내장 소프트웨어의 품질이 향상됩니다.

a) "더 나은"C

C ++는 강력한 유형의 언어입니다. C보다 강력합니다. 프로그램에서이 기능을 활용할 수 있습니다.

어떤 사람들은 포인터를 두려워합니다. C ++에는 참조가 포함되어 있습니다. 과부하 된 기능.

그리고 말할 가치가 있습니다.이 기능들 중 어느 것도 더 크거나 느린 프로그램에서 발생하지 않았습니다.

b) 그것은 객체 지향 언어입니다

이 포스트에서 누군가는 마이크로 컨트롤러에서 머신을 추상화하는 것은 좋은 생각이 아니라고 말했다. 잘못된! 임베디드 엔지니어 인 우리 모두는 항상 C ++과는 다른 방식으로 기계를 추상화했습니다. 이 논증으로 볼 수있는 문제는 일부 프로그래머가 객체를 생각하는 데 익숙하지 않다는 것인데, OOP의 이점을 보지 못하는 방식입니다.

마이크로 컨트롤러의 주변 장치를 사용할 준비가되면 주변 장치가 장치 드라이버의 형태로 (자신 또는 제 3 자로부터) 추상화되어있을 가능성이 있습니다. 앞에서 말했듯이 다음 예제에서 볼 수 있듯이 해당 드라이버는 C sintax를 사용합니다 (NXP LPC1114 예제에서 직접 가져옴).

/ * TICKRATE_HZ에서 일치 및 인터럽트를위한 타이머 설정 * /

Chip_TIMER_Reset (LPC_TIMER32_0);

Chip_TIMER_MatchEnableInt (LPC_TIMER32_0, 1);

Chip_TIMER_SetMatch (LPC_TIMER32_0, 1, (timerFreq / TICKRATE_HZ2));

Chip_TIMER_ResetOnMatchEnable (LPC_TIMER32_0, 1);

Chip_TIMER_Enable (LPC_TIMER32_0);

추상화가 보입니까? 따라서 동일한 목적으로 C ++를 사용할 때 C ++의 추상화 및 캡슐화 메커니즘을 통해 추상화가 한 단계 높은 비용으로 제공됩니다!

c) 일반적인 프로그램을 작성할 수있는 언어입니다.

일반 프로그램은 템플릿을 통해 이루어지며 템플릿에는 비용이 들지 않습니다.

게다가, 정적 다형성은 템플릿으로 달성됩니다.

가상 방법, RTTI 및 예외.

가상 방법을 사용할 때 타협이 있습니다 : 더 나은 소프트웨어 대 성능 저하. 그러나 동적 바인딩은 가상 테이블 (함수 포인터의 배열)을 사용하여 구현 될 수 있습니다. 나는 C에서 똑같이 많은 시간을 보냈기 때문에 (정기적으로도) 가상 메소드를 사용하는 데 따른 단점을 보지 못합니다. 또한 C ++의 가상 메소드가 더 우아합니다.

마지막으로 RTTI 및 예외에 대한 조언 : 임베디드 시스템에서 사용하지 마십시오. 모든 비용을 피하십시오 !!


2

내 배경, 임베디드 (mcu, pc, unix, 기타), 실시간. 안전이 중요합니다. 이전 고용주를 STL에 소개했습니다. 나는 더 이상 그렇게하지 않습니다.

일부 화염 내용

C ++는 임베디드 시스템에 적합합니까?

Meh. C ++는 작성하는 데 어려움과 유지해야 할 고통입니다. C +는 괜찮습니다 (일부 기능은 사용하지 마십시오)

마이크로 컨트롤러의 C ++? RTOS? 토스터? 임베디드 PC?

다시 Meh를 말합니다. C +는 그렇게 나쁘지는 않지만 ADA는 덜 고통 스럽습니다 (그리고 실제로 무언가를 말하고 있습니다). 운이 좋으면 임베디드 Java를 할 수 있습니다. 배열 액세스를 확인하고 포인터 산술이 없으면 매우 안정적인 코드가 만들어집니다. 임베디드 Java의 가비지 콜렉터는 최우선 순위가 아니며 범위가 지정된 메모리 및 오브젝트 재사용이 있으므로 잘 설계된 코드는 GC 없이도 영원히 실행될 수 있습니다.

마이크로 컨트롤러에서 OOP가 유용한가요?

당연히. UART는 객체입니다 ..... DMAC는 객체입니다 ...

객체 상태 머신은 매우 쉽습니다.

C ++는 프로그래머를 하드웨어에서 너무 멀리 제거하여 효율적입니까?

PDP-11이 아닌 한 C는 CPU가 아닙니다. C ++은 원래 C의 전 처리기 였기 때문에 AT & T에서 Bjarne Stroustrup이 Simula 시뮬레이션을 느리게하는 것에 대해 웃지 않을 것입니다. C ++은 CPU가 아닙니다.

자바 바이트 코드를 실행하는 MCU를 가져 가십시오. 자바 프로그램. C 사람들을 비 웃으십시오.

Arduino의 C ++ (동적 메모리 관리, 템플릿, 예외가없는)를 "실제 C ++"로 간주해야합니까?

아니. MCU에 대한 모든 나쁜 C 컴파일러와 마찬가지로.

넷째, 임베디드 자바 또는 임베디드 ADA는 표준화되어 있습니다. 다른 모든 것은 슬픔입니다.


2
Java를 지원하는 마이크로 컨트롤러를 쉽게 찾을 수 있습니까? 나는 이것이 선택을 상당히 제한 할 것이라고 생각합니다. 그리고 성능 저하에 대한 경험은 무엇입니까 (일반적으로 JIT가없는 uC이므로)? 실시간 시스템에서 GC 예측 불가의 영향은 어떻습니까?
fceconel

2
임베디드 Java를 지원하는 MCU는 무엇입니까?
J. Polfer

초보자를위한 www.ajile.com
Tim Williscroft

에이다 +1 Arduinos를 포함하여 임베디드에 많이 사용됩니다.
Brian Drummond 2014

c로 작성된 마이크로 용 휴대용 Java VM은 오픈 소스입니다. dmitry.co/index.php?p=./04.Thoughts/…
Tim Williscroft

-2

임베디드 시스템은 여러 작업을위한 범용 컴퓨터가 아닌 특정 작업을 수행하도록 설계되었습니다. 임베디드 시스템은 컴퓨터 하드웨어와 소프트웨어의 조합입니다. C는 모든 현대 언어의 어머니입니다. 저수준이지만 강력한 언어이며 모든 종류의 하드웨어를 처리합니다. 따라서 C / C ++는 임베디드 시스템 용 소프트웨어를 개발하기위한 최적의 선택이며 모든 임베디드 시스템에 매우 많이 사용됩니다. 우리는 C가 개발 언어라는 것을 알고 있습니다. 운영 체제 UNIX는 C로 작성되었습니다. 성공적인 소프트웨어 개발은 ​​주어진 프로젝트에 가장 적합한 언어를 선택하는 데 자주 사용되므로 C / C ++ 언어가 8 비트 및 64 비트 프로세서 모두에 적합한 것으로 판명 된 것은 놀라운 일입니다. ; 바이트, 킬로바이트 및 메가 바이트의 메모리가있는 시스템에서. C는 프로세서 독립성의 이점을 가지고 있습니다. 이를 통해 프로그래머는 특정 프로세서 아키텍처의 세부 사항보다는 알고리즘 및 응용 프로그램에 집중할 수 있습니다. 그러나 이러한 장점 중 많은 부분이 다른 고급 언어에도 동일하게 적용됩니다. 그러나 많은 다른 언어가 크게 실패한 곳에서 C / C ++가 성공 했습니까?


6
이것이 이것이 토론에 추가하는 것이 확실하지 않습니다.
Dave Tweed

-3

<랜트>

C ++은 처음에는 엉터리 언어라고 생각합니다. OOP를 사용하려면 Java 프로그램을 작성하십시오. C ++은 직접 메모리 액세스가 (ab) 사용할 수있는 권한 내에 있으므로 OOP 패러다임을 강제 할 것은 없습니다.

MCU가 있다면 플래시 메모리가 100kB 미만일 가능성이 높습니다. 메모리 추상화가있는 언어로 프로그래밍하려고합니다 : 변수 또는 배열을 선언하면 메모리, 기간을 얻습니다. malloc (일명 C ++에서 "새"키워드)은 프로그램 시작 중 한 번의 호출로 드문 경우를 제외하고는 임베디드 소프트웨어에서 사용을 금지해야합니다.

C가 충분히 저수준이 아닌 임베디드 프로그래밍에는 종종 (빈번한) 시간이 있으며, 레지스터에 변수를 할당하고 인터럽트 서비스 루틴 (ISR)을 강화하기 위해 인라인 어셈블리를 작성하는 것과 같은 작업을 수행해야합니다. "휘발성"과 같은 키워드는 이해하기가 매우 중요합니다. 객체 수준이 아닌 비트 수준 에서 메모리를 조작하는 데 많은 시간을 소비 합니다.

왜 사실보다 실제가 더 단순하다는 생각에 빠져들고 싶습니까?

</ rant>


내 문제는 간단하게 왜 USART1이 인터페이스를 처리하기 위해 완전히 개발 된 경우 USART1을 제어하기 위해 작성된 드라이버의 복잡성을 알고 싶습니까?
Kortuk

1
나는 당신에게 투표하지 않았지만 C ++은 OOP를 시행 할 필요가 없으며 도구를 제공한다고 지적하고 싶습니다. 좋은 코딩 표준을 적용하는 것은 개발자의 일입니다. 언어가 더 쉬워지면 도움이 될 수 있지만, 언어 자체로는 그렇게하지 않을 것입니다. 경우에 따라 C를 읽을 수 없습니다.
Kortuk

1
모든 언어는 무언가에 좋습니다. C ++은 빠릅니다. OOP를 잘 수행하면 여러 개발자가 병렬 작업을 수행하고 알 수없는 코드를 훨씬 쉽게 작성할 수 있습니다. 이것이 게임 개발에 많은 관심을 끄는 이유라고 생각합니다.
Toby Jaffey 2016 년

1
그래, 난 동의. 임베디드 세계에서 내가 보는 이유는 이미 존재하는 다양한 시스템에 새로운 기능이 추가되고 새로운 시스템이 개발 되었기 때문입니다. 프로젝트가 점점 커집니다. 우리는 그것들을 개발하는 데 시간이 더 걸리거나 CS 세계가 이미 PC에서 한 일을 적용하고 왜곡하기 시작합니다.
Kortuk

5
C ++을 제대로 이해하지 못하는 다른 사람. 얼마나 많은지 항상 놀라워합니다.
Rocketmagnet
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.