여기와 다른 곳에서 일반적인 질문입니다. C ++는 임베디드 시스템에 적합합니까?
마이크로 컨트롤러? RTOS? 토스터? 임베디드 PC?
마이크로 컨트롤러에서 OOP가 유용한가요?
C ++는 프로그래머를 하드웨어에서 너무 멀리 제거하여 효율적입니까?
Arduino의 C ++ (동적 메모리 관리, 템플릿, 예외가없는)를 "실제 C ++"로 간주해야합니까?
(이 위키는이 잠재적 인 거룩한 전쟁을 담을 장소가 될 것입니다)
여기와 다른 곳에서 일반적인 질문입니다. C ++는 임베디드 시스템에 적합합니까?
마이크로 컨트롤러? RTOS? 토스터? 임베디드 PC?
마이크로 컨트롤러에서 OOP가 유용한가요?
C ++는 프로그래머를 하드웨어에서 너무 멀리 제거하여 효율적입니까?
Arduino의 C ++ (동적 메모리 관리, 템플릿, 예외가없는)를 "실제 C ++"로 간주해야합니까?
(이 위키는이 잠재적 인 거룩한 전쟁을 담을 장소가 될 것입니다)
답변:
예, 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보다 더 잘 작동 할 수 있지만 다시 한 번, 자신을 교육하고 방법을 배우는 것을 두려워하지 마십시오.
C ++는 임베디드 시스템에 절대적으로 적합합니다. 이제 특정 마이크로 프로세서를 사용할지 여부에 대한 기본 기준으로 우수한 개발 도구의 유무 (또는 부족)를 사용합니다.
리소스 비용이 낮기 때문에 임베디드 시스템에서 사용하기에 좋은 C ++ 영역 :
확인 영역 :
주로 소규모 시스템에서는 허용되지 않는 런타임 오버 헤드로 인해 사용하지 않는 영역 :
foo
호출 하고 일부 객체와 호출을 생성 하여 예외를 발생시키는 경우 시스템은 제어를에 반환하기 전에 생성 된 객체에 대해 소멸자를 호출해야 한다는 것 입니다. 예외가 완전히 비활성화되지 않는 한, 예외가 발생 하는지 알 수 있는 방법이 없으므로 해당 가능성을 허용하기 위해 추가 코드를 포함해야합니다. 이를 처리하기 위해 "체크 된 예외"가있는 C ++의 변형을보고 싶습니다. 예외를 피할 수있는 루틴이라면 ...bar
try
catch
bar
boz
bar
foo
bar
boz
add r15,r14,#2
대신에 정상적으로 종료됩니다 mov r15,r14
. 예외를 통해 종료하려면 ldrhs r0,[r14] / add r15,r14,r0
. 정상 종료에 대한 사이클 비용이없고 스택 프레임 제한이 없습니다.
예, 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 ++는 다음에 대한 향상된 지원을 제공합니다.
이러한 기능 중 어느 것도 C의 일반적인 기능보다 무겁지 않습니다.
최대 16 또는 32 비트 MCU로 이동할 때 C의 더 무거운 기능 (스택, 힙, 포인터, 어레이, printf 등)을 사용하는 것이 합리적입니다. 같은 방식으로 더 강력한 MCU가 적합 해집니다 C ++의 더 무거운 기능 (스택, 힙, 참조, STL, 새 / 삭제)을 사용합니다.
따라서 PIC16에서 C ++에 대해 생각할 필요가 없습니다. 자신의 언어와 MCU를 제대로 알고 있다면, 두 언어를 효과적으로 함께 사용하는 방법을 알게 될 것입니다.
a[i] = b[j] * c[k];
변수의 특성에 따라 약 4 페이지의 명령어를 생성 할 수 있습니다." MCU / 컴파일러가이 작업을 수행하는 경우 80 년대의 일부 차고 애호가 CPU를 사용하고 있기 때문입니다.
나는 항상이 토론이 재미있는 것을 발견합니다. 사용 가능한 다양한 언어의 장단점에 대한 지적 토론은 그리 많지 않지만 일반적으로 자신의 직업 / 경험 / 관심 분야에 따라 주제에 대한 누군가의 입장을 찌를 수 있기 때문입니다. CS 조기 전공과 유지 보수 프로그래머들이 Knuth를 좌우로 인용하고 성능 문제가 모두 미쳤다고 생각하는 실제 세계에서 일하는 사람들은 "조기 최적화"라는 주장과 함께 바로 거기에 있습니다 (후자 그룹의 구성원입니다) 공정하게).
하루가 끝나면 C 또는 C ++로 우수한 소프트웨어를 개발하거나 여기에 언어를 삽입 할 수 있습니다 . 언어가 아닌 개발자의 능력에 달려 있습니다. 언어 전문가가 되려면 일반적으로 잘못된 언어를 선택하여 문제를 해결하기 위해 언어를 변형해야하는 경우에만 필요합니다. 대부분의 경우 이러한 기능은 모호한 기능이나 컴파일러로 뛰어 들어야하는 유일한 상황입니다 목표를 달성하기위한 속임수.
나는 사람들이 이러한 주장을 "언어 X와 블라 블라 (Blah Blah)의 전문가"라고 시작하는 것을 종종 듣는다. 내 의견으로는, 그들은 이미 잘못된 각도에서 문제에 접근했고 그 이후의 모든 것이 오염 되었기 때문에 솔직히이 사람들을 불신한다. 도구를 사용하여 문제를 해결하고 얼마나 '멋진'지를 보여주기를 원합니다.
나는 종종 개발자들이 도구 세트를 먼저 선택하고 문제를 두 번째로 구부리려고 시도하는 것을 보았습니다.
다른 답변에 대한 언급에서 언급했듯이, 이러한 언어 전쟁은 종종 언어 X가 프로그래머가 더 멍청한 일을 할 수 있다고 주장합니다. 읽는 것이 즐겁지만, 이러한 모든 진술은 실제로 훌륭한 개발자를 고용하는 데 문제가 있고 나쁜 개발자를 계속 고용하고 상황이 작은 개발자가 할 수있는 도구를 선택하여 상황을 돕지 않고 직접 문제를 해결해야한다는 것을 의미합니다 가능한 피해.
제 생각에는 소프트웨어 나 하드웨어 개발, 문제 조사, 솔루션 설계, 솔루션을 '최고의 방법으로'표현할 수있는 도구를 찾는 좋은 개발자입니다. 새로운 도구를 선택하는 프로젝트에 3-4 개 언어 / 개발 도구를 사용한 후에는 필요한 도구가 이전에 사용해 본 적이없는 도구인지 여부는 중요하지 않습니다. 개발 시간에 최소한의 영향을 미칩니다.
물론 '최상의 방법'은 주관적인 용어이며 연구 단계에서 정의해야합니다. 성능, 표현의 용이성, 코드 밀도 등과 같은 여러 가지 문제를 고려해야합니다. 적절한 이유로 도구를 선택하고 이것이 '무료'라는 문제를 이해하는 데 시간을 들인 경우, 선택한 언어에 상관없이 목록에 유지 관리 기능을 포함시키지 않았습니다. 코드를 유지하기 어려운 것은 종종 잘못된 도구 나 열악한 시스템 구조를 선택한 결과이며, 이로 인해 코드가 제대로 작동하지 않는 경우가 있습니다.
어떤 언어가 다른 언어보다 '더 나은'것이라고 주장하는 것은 관심있는 특정 문제를 정의하지 않고 어리석은 일입니다. 객체 지향 접근법이 항상 기능적 접근법보다 낫지는 않습니다. 객체 지향 디자인 패러다임에 매우 적합한 몇 가지 문제가 있습니다. 그렇지 않은 많은 사람들이 있습니다. 사람들이 좋아하는 많은 언어 기능에 대해서도 같은 말을 할 수 있습니다.
실제로 코드를 입력하는 문제에 시간의 20 % 이상을 소비하는 경우 시스템 성능이 매우 좋지 않거나 개발자가 매우 열악한 것입니다 (또는 여전히 배우고 있음). 문제의 다이어그램을 작성하고 다양한 응용 프로그램이 상호 작용하는 방식을 결정하는 데 대부분의 시간을 투자해야합니다. 마커 보드와 문제를 해결하기 위해 문제가있는 방에 재능있는 개발자 그룹을 고수하고 전체 시스템에 익숙해지기 전에는 코드를 작성하거나 도구를 선택할 수 없습니다. 개발 시간을 단축 할 수있는 새로운 도구를 선택하는 것보다 출력 및 개발 속도가 빠릅니다. (내 주장과 반대되는 극점에 대한 참조로 스크럼 개발을 찾아보십시오)
불행히도 현실은 많은 기업들이 작성된 줄 수 또는 '유형 산출물'로만 개발자의 가치를 측정 할 수 있다는 것입니다. 그들은 마커 보드가있는 방에서 3 주를 생산성 손실로 봅니다. 개발자들은 종종 '생각'개발 단계를 거쳐야하거나 회사 내 정치적 문제에 의해 설정된 도구를 사용하도록 강요받습니다. "내 상사의 형제는 IBM을 위해 일하기 때문에 도구 만 사용할 수 있습니다." . 더 나쁜 것은 적절한 시장 조사를 할 수 없거나 개발주기에 대한 변경의 영향을 이해하지 못하기 때문에 회사에서 끊임없이 변화하는 요구 사항을 얻는 것입니다.
이 폭언으로 주제를 벗어난 것에 대해 유감스럽게 생각합니다. 저는이 주제에 대해 매우 강한 의견을 가지고 있습니다.
모든 언어는 임베디드 시스템에 적합 할 수 있습니다. 임베디드는 단지 사용하기 쉬운 컴퓨터가 아니라 더 큰 장치의 일부를 의미합니다.
이 질문은 (실시간) 실시간 또는 제한된 자원 시스템을 요청할 때 더 관련성이 있습니다.
실시간 시스템의 경우 C ++은 엄격한 시간 제약 조건을 프로그래밍 할 때 여전히 적합한 최고 언어 중 하나입니다. 힙 사용 (무료 연산자)을 제외하고는 실행 시간이 확정되지 않은 구성 요소가 없으므로 프로그램이 타이밍 요구 사항을 충족하는지 여부를 테스트 할 수 있으며 경험이 더 있으면이를 예측할 수도 있습니다. 물론 새로운 연산자는 일회성 할당에 사용될 수 있지만 힙 사용은 피해야합니다. C ++가 C보다 제공하는 구성은 임베디드 시스템 (OO, 예외, 템플릿)에서 잘 활용할 수 있습니다.
리소스 제한이 매우 높은 시스템 (8 비트 칩, 몇 Kb 미만의 RAM, 충분한 스택 없음)의 경우 전체 C ++은 여전히 '더 나은 C'로 사용될 수 있지만 적합하지 않을 수 있습니다.
나는 아이다가 일부 틈새 시장에서만 사용되는 것 같습니다. 여러 가지면에서 그것은 파스칼 ++이지만, 이미 시작하기에 이미 엉망인 언어와 호환되는 부담이 없습니다. (편집 : 심각한 혼란은 물론 C입니다. 파스칼은 아름답지만 다소 비현실적인 언어입니다.)
===================================================== ==============
편집 : 나는이 질문에 대해 폐쇄 된 새로운 질문 ( "어떤 경우에 우리가 마이크로 컨트롤러를 프로그래밍 할 때 C ++이 필요한가?")에 대한 답을 입력하고 있었으므로 내가 쓴 것을 추가 할 것입니다.
의 사용에 대한 모든-위압 이유가 결코 어떤 프로그래밍 언어, 특정 상황에서 더 많거나 적은 무게를 인수있을 수 있습니다. 이에 대한 논의는 "마이크로 컨트롤러에 C ++을 사용하지 마십시오"에서 "항상 C ++을 사용"하는 위치까지 다양한 위치에서 찾을 수 있습니다. 나는 마지막 위치에 더 있습니다. 나는 몇 가지 주장을 할 수는 있지만 특정 상황에서 (그리고 어느 방향으로) 얼마나 많은 무게를 지니고 있는지 스스로 결정해야합니다.
내 블로그 에는 소형 시스템 (= 마이크로 컨트롤러)에서 C ++ 사용에 대한 글이 있습니다.
내 경험상 C ++은 일반적으로 소형 임베디드 시스템에는 적합하지 않습니다. 즉, 마이크로 컨트롤러 및 OS없는 장치입니다.
많은 C ++ OOP 기술은 동적 메모리 할당에 의존합니다. 소규모 시스템에서는 종종 누락됩니다.
STL과 Boost는 실제로 C ++의 힘을 보여줍니다.
C ++은 프로그래머가 기계를 추상화하여 제약 된 시스템에서 수용해야한다고 권장합니다.
작년에 상용 원격 데스크톱 제품을 휴대 전화로 이식했습니다. C ++로 작성되었으며 Windows, Linux 및 OSX에서 실행되었습니다. 그러나 STL, 동적 메모리 및 C ++ 예외에 크게 의존했습니다. WinCE, Symbian 및 OS없는 환경에서 C 재 작성이 가장 좋은 옵션이었습니다.
베어 메탈 및 리소스 제한 시스템의 C ++에 대한이 토론에 열보다 많은 빛을 추가하고 싶습니다.
C ++의 문제점 :
필요한 "비상 버퍼"(예를 들어, 메모리 부족 예외가 발생하는 경우)가 사용 가능한 RAM보다 클 수 있고 마이크로 컨트롤러의 낭비 일 수 있으므로 예외는 특히 RAM 문제입니다. 자세한 정보는 n4049 및 n4234를 참조하십시오 . 꺼야합니다 (현재 지정되지 않은 동작이므로 반드시 버리지 마십시오). 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가 아니지만 something
int를 표현 방법으로 사용하는 즉시 잘못된 데이터를 전달할 수없는 함수가 실제로 거의 없습니다. 잘못되었습니다 ( '무언가'가 아닌 잘못된 값이나 'otherThing'을 전달하십시오). C에서 사용자가 잘못했는지 확인하는 유일한 방법은 런타임입니다. C ++에서는 모든 검사가 아니라 컴파일 타임에 일부 검사가 무료 인 검사를 수행 할 수 있습니다.
하루가 끝나면 C 팀은 가장 약한 프로그래머만큼 강력하며 결과 코드의 이점은 멀티 플레이 1 또는 성능 저하입니다. 이것이 의미하는 바는 독특한 디자인 결정의 독특한 환경에서 하나의 유일한 작업에 대한 고성능이거나 여러 환경 (다른 마이크로 컨트롤러, 다른 메모리 관리 전략, 다른 대기 시간 vs. 처리량 트레이드 오프 등)이지만 고유 한 성능 비용이 있습니다.
C ++에서는 사물을 전문가가 캡슐화 할 수 있으며 컴파일 타임 코드 생성이 특정 작업에 적응하고 정적 검사를 통해 사용자가 비용없이 바보 같은 일을 수행하지 못하게하는 많은 환경에서 사용될 수 있습니다. 여기서 우리는 일반적인 것과 빠른 것 사이의 거래가 훨씬 적으므로 궁극적으로 비용 대 이익 관점에서 더 성능적이고 안전하며 생산적인 언어입니다.
임베디드 용으로 좋은 C ++ 라이브러리가 여전히 부족하다는 사실은 유효한 비판이며, 이는 C ++ 컴파일러에서 C를 주로 사용하는 실용적인 결정으로 이어질 수 있습니다. 프로젝트에서 C 만 사용하기로 한 결정은 근본적으로 이념적으로, 레거시 지원이 필요하지 않거나 팀이 C ++에서는 할 수 있지만 C에서는 할 수없는 엄청나게 바보 같은 일을 자제 할만큼 훈련을받지 않았다는 인정 동시에 C에서는 보호 할 수 없지만 C ++에서는 할 수없는 훨씬 더 어리석은 일을하지 않도록 충분히 훈련을 받았습니다.
저의 배경 : 오래된 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 ++에서 더 단순하게 만듭니다 (객체에 데이터를 캡슐화하여 동적 메모리를 자동으로 소멸시킵니다). 모든 메모리 위치가 중요한 일부 응용 프로그램에서는 관리하기에 너무 거칠고 울퉁불퉁 할 수 있습니다.
편집하다:
그렇습니다. C ++의 문제는 코드의 발자국 증가입니다.
일부 시스템에서는 바이트 수를 계산하는 경우 시스템 경계에 근접한 실행 비용이 C의 개발 비용 증가에 해당하는 운영 비용을 수용해야합니다.
그러나 C에서도 잘 설계된 시스템의 경우 모든 것을 캡슐화해야합니다. 잘 설계된 시스템은 어렵고 C ++은 프로그래머에게 매우 체계적이고 통제 된 개발 방법을 제공합니다. OOP를 배우는 데 비용이 들며,이를 전환하려면 많은 동의를해야하며, 대부분의 경우 관리는 C로 계속 진행하고 비용을 지불하지 않을 것입니다. 스위치의 결과를 측정하기가 어렵 기 때문입니다. 생산성을 향상시킵니다. 임베디드 시스템 전문가 인 Jack Ganssle 의 기사를 여기서 볼 수 있습니다 .
동적 메모리 관리는 악마입니다. 실제로, 악마는 자동 경로 지정이 아니며 동적 메모리 관리는 PC에서 훌륭하게 작동하지만 최소한 몇 주마다 PC를 다시 시작할 것으로 기대할 수 있습니다. 임베디드 시스템이 5 년 동안 계속 작동함에 따라 동적 메모리 관리가 실제로 망쳐 져 실제로 실패하기 시작할 수 있습니다. Ganssle은 그의 기사에서 스택 및 힙과 같은 것을 논의합니다.
C ++에는 문제를 일으키기 쉽고 많은 리소스를 사용하는 경향이있는 것들이 있습니다. 동적 메모리 관리를 제거하고 템플릿은 C ++의 풋 프린트를 C의 풋 프린트에 가깝게 유지하는 큰 단계입니다. 여전히 C ++이므로 동적이 필요하지 않습니다. 좋은 C ++를 작성하기위한 메모리 관리 또는 템플릿. 나는 그들이 예외를 제거한다는 것을 몰랐다. 나는 예외를 릴리스에서 제거하는 코드의 중요한 부분으로 생각하지만 그 시점까지 사용한다. 현장 테스트에서 예외가 포착되고 있음을 알려주는 메시지를 생성하도록 예외를 가질 수 있습니다.
나는 생각 이 안티 C ++ 호언 장담 리누스 토발즈 (Linus Torvalds)에 의해이 흥미로웠다.
C ++의 최악의 기능 중 하나는 상황에 따라 많은 것을 만드는 것입니다. 즉, 코드를 볼 때 로컬 뷰는 상황을 알기에 충분한 컨텍스트를 거의 제공하지 않습니다.
그는 임베디드 시스템 세계가 아니라 Linux 커널 개발에 대해 이야기하고 있습니다. 나에게 관련성은 이것에서 비롯됩니다 : C ++은 더 큰 컨텍스트를 이해해야하며 일련의 객체 템플릿을 사용하는 법을 배울 수 있습니다. 몇 달 안에 코드를 업데이트해야 할 때 템플릿을 기억할 것을 믿지 않습니다.
(반면에, 나는 현재 그 문제를 겪을 파이썬 (C ++이 아니라 동일한 OOP 패러다임을 사용하는)을 사용하는 임베디드 장치에서 작업하고 있습니다. 내 방어에서는 PC라고 할 정도로 강력한 임베디드 시스템입니다 10 년 전)
다른 답변이 장단점과 의사 결정 요인에 대해 꽤 좋은 사례라고 생각합니다. 따라서 몇 가지 의견을 요약하고 추가하고 싶습니다.
소형 마이크로 컨트롤러 (8 비트)의 경우에는 없습니다. 당신은 자신을 다치게 요구하고 있습니다. 이득이 없으며 너무 많은 자원을 포기할 것입니다.
괜찮은 OS를 가진 하이 엔드 마이크로 컨트롤러 (예 : RAM 및 스토리지의 경우 32 비트, 10 또는 100MB)의 경우 완벽하게 작동하며 권장 할만한 제품입니다.
문제는 경계가 어디입니까?
확실하지는 않지만 C ++에서 1MB RAM 및 1MB 저장 공간을 갖춘 16 비트 uC 용 시스템을 개발 한 후에는 나중에 유감스럽게 생각합니다. 예, 효과가 있었지만 추가 작업은 그만한 가치가 없었습니다. 나는 예외와 같은 것들이 누수를 일으키지 않도록해야했습니다 (OS + RTL 지원은 버그가 많고 신뢰할 수 없었습니다). 또한 OO 앱은 일반적으로 많은 작은 할당을 수행하며 힙 오버 헤드는 또 다른 악몽이었습니다.
이러한 경험을 바탕으로 향후 프로젝트에서는 최소 16 비트, RAM 및 스토리지 용으로 최소 16MB의 시스템에서만 C ++을 선택한다고 가정합니다. 그것은 임의의 한계이며 응용 프로그램의 유형, 코딩 스타일 및 관용구 등에 따라 다를 수 있습니다. 그러나주의 사항을 감안할 때 비슷한 접근법을 권장합니다.
임베디드 시스템에 유용한 C ++의 일부 기능이 있습니다. 예외와 같이 비쌀 수 있으며 비용이 항상 명백하지 않을 수도있는 다른 것들도 있습니다.
만약 내가 진실을 알고 있다면, 두 세계의 장점을 모두 갖춘 인기있는 언어가있을 것이며 두 언어 모두에서 부족한 몇 가지 특징이 포함되었습니다. 일부 공급 업체에는 이러한 기능이 포함되어 있지만 표준은 없습니다. 보고 싶은 몇 가지 :
인라인 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를 사용하는 것보다 약간의 개선을 제공 할 수 있다고 생각합니다.
위와 같은 표준이 모든 유형의 표준에 고려되고 있는지 아는 사람이 있습니까?
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 및 예외에 대한 조언 : 임베디드 시스템에서 사용하지 마십시오. 모든 비용을 피하십시오 !!
내 배경, 임베디드 (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는 표준화되어 있습니다. 다른 모든 것은 슬픔입니다.
임베디드 시스템은 여러 작업을위한 범용 컴퓨터가 아닌 특정 작업을 수행하도록 설계되었습니다. 임베디드 시스템은 컴퓨터 하드웨어와 소프트웨어의 조합입니다. C는 모든 현대 언어의 어머니입니다. 저수준이지만 강력한 언어이며 모든 종류의 하드웨어를 처리합니다. 따라서 C / C ++는 임베디드 시스템 용 소프트웨어를 개발하기위한 최적의 선택이며 모든 임베디드 시스템에 매우 많이 사용됩니다. 우리는 C가 개발 언어라는 것을 알고 있습니다. 운영 체제 UNIX는 C로 작성되었습니다. 성공적인 소프트웨어 개발은 주어진 프로젝트에 가장 적합한 언어를 선택하는 데 자주 사용되므로 C / C ++ 언어가 8 비트 및 64 비트 프로세서 모두에 적합한 것으로 판명 된 것은 놀라운 일입니다. ; 바이트, 킬로바이트 및 메가 바이트의 메모리가있는 시스템에서. C는 프로세서 독립성의 이점을 가지고 있습니다. 이를 통해 프로그래머는 특정 프로세서 아키텍처의 세부 사항보다는 알고리즘 및 응용 프로그램에 집중할 수 있습니다. 그러나 이러한 장점 중 많은 부분이 다른 고급 언어에도 동일하게 적용됩니다. 그러나 많은 다른 언어가 크게 실패한 곳에서 C / C ++가 성공 했습니까?
<랜트>
C ++은 처음에는 엉터리 언어라고 생각합니다. OOP를 사용하려면 Java 프로그램을 작성하십시오. C ++은 직접 메모리 액세스가 (ab) 사용할 수있는 권한 내에 있으므로 OOP 패러다임을 강제 할 것은 없습니다.
MCU가 있다면 플래시 메모리가 100kB 미만일 가능성이 높습니다. 메모리 추상화가있는 언어로 프로그래밍하려고합니다 : 변수 또는 배열을 선언하면 메모리, 기간을 얻습니다. malloc (일명 C ++에서 "새"키워드)은 프로그램 시작 중 한 번의 호출로 드문 경우를 제외하고는 임베디드 소프트웨어에서 사용을 금지해야합니다.
C가 충분히 저수준이 아닌 임베디드 프로그래밍에는 종종 (빈번한) 시간이 있으며, 레지스터에 변수를 할당하고 인터럽트 서비스 루틴 (ISR)을 강화하기 위해 인라인 어셈블리를 작성하는 것과 같은 작업을 수행해야합니다. "휘발성"과 같은 키워드는 이해하기가 매우 중요합니다. 객체 수준이 아닌 비트 수준 에서 메모리를 조작하는 데 많은 시간을 소비 합니다.
왜 사실보다 실제가 더 단순하다는 생각에 빠져들고 싶습니까?
</ rant>