ここと他の場所でよくある質問。C ++は組み込みシステムに適していますか?
マイクロコントローラー?RTOS?トースター?組み込みPC?
OOPはマイクロコントローラーで役立ちますか?
C ++はプログラマーをハードウェアから遠ざけすぎて効率的にしませんか?
ArduinoのC ++(動的メモリ管理、テンプレート、例外なし)を「実際のC ++」と見なすべきですか?
(うまくいけば、このwikiはこの潜在的な聖戦を封じ込める場所として役立つでしょう)
ここと他の場所でよくある質問。C ++は組み込みシステムに適していますか?
マイクロコントローラー?RTOS?トースター?組み込みPC?
OOPはマイクロコントローラーで役立ちますか?
C ++はプログラマーをハードウェアから遠ざけすぎて効率的にしませんか?
ArduinoのC ++(動的メモリ管理、テンプレート、例外なし)を「実際のC ++」と見なすべきですか?
(うまくいけば、このwikiはこの潜在的な聖戦を封じ込める場所として役立つでしょう)
回答:
はい、C ++は組み込みシステムで引き続き有用です。他のみんなが言ったように、それはまだシステム自体に依存しています。たとえば、8ビットuCは、コンパイラがあり、一部の人々はそれをしますが(シャダー)、私の本ではおそらくノーノーでしょう。8ビットのマイクロの世界でさえ、C ++を「C +」のようなものに縮小する場合でも、C ++を使用することには利点があります。「C +」とはどういう意味ですか?つまり、new / deleteを使用しない、例外を回避する、継承のある仮想クラスを回避する、おそらく継承をすべて回避する、テンプレートに非常に注意する、マクロの代わりにインライン関数を使用const
する、の代わりに変数を使用するということです#defines
。
組み込みシステムのCとC ++の両方で10年以上働いてきましたが、C ++に対する若々しい熱意のいくつかは、素朴さを揺さぶる現実世界の問題のために確実に消耗しました。組み込みシステムで最悪のC ++を見たことがありますが、これを「CSプログラマーがEEの世界に突入した」と呼びたいと思います。実際、これはクライアントと一緒に取り組んでいるもので、クライアントが持っているこの1つのコードベースを改善しています。
C ++の危険性は、言語と一般的なプログラミング自体で適切に教育および訓練されていなければ、腕と脚の両方を切断できる両刃の剣のような非常に強力なツールだからです。Cは片刃の剣に似ていますが、それでも同じくらい鋭利です。C ++では、非常に高レベルの抽象化を取得し、長期的には意味をなさない難読化されたインターフェイスを作成するのは簡単すぎます。これは、C ++がさまざまな言語機能(テンプレート、OOP、手続きRTTI、OOP +テンプレート、オーバーロード、インライン化)。
C ++の第一人者Scott Meyersによる、C ++の組み込みソフトウェアに関する2つの4時間のセミナーを終了しました。彼は、私がこれまで考えたことがなかったテンプレートについてのいくつかのことと、どれだけ安全性が重要なコードの作成に役立つかを指摘しました。その要点は、厳格な安全重視のコード要件を満たさなければならないソフトウェアにデッドコードを入れることはできないということです。コンパイラーはテンプレートのインスタンス化時に必要なコードのみを作成するため、テンプレートはこれを実現するのに役立ちます。ただし、リンカは常にデッドコードを最適化するとは限らないため、Cで達成するのが難しいこの機能を正しく設計するために、使用方法を徹底的に教育する必要があります。
スコット・マイヤーズは、テンプレートとインライン化の賢明な使用に関する非常に大きな支持者であり、テンプレートについて熱心であることにまだ懐疑的であると言わざるを得ません。彼は彼らが最高のツールになる場所にのみ適用されるべきだと言っているにもかかわらず、私はそれらを敬遠する傾向があります。彼はまた、C ++が、使いやすく、間違った使い方をしにくい、本当に優れたインターフェースを作成するツールを提供していると指摘しています。繰り返しますが、それは難しい部分です。これらの機能を最も効率的な方法で適用して最適な設計ソリューションにする方法を知るには、C ++の習熟レベルに到達する必要があります。
OOPについても同じことが言えます。組み込みの世界では、ランタイムポリモーフィズムのランタイムコストを処理できるかどうかを知るために、コンパイラがどのようなコードを吐き出すかを理解する必要があります。設計が納期の要件を満たしていることを証明するために、測定も行う必要があります。その新しいInterruptManagerクラスは、割り込みレイテンシを長くしすぎますか?Cでもできるリンク時ポリモーフィズムなど、あなたの問題によりよく適合するポリモーフィズムには他の形式がありますが、C ++ではPimplデザインパターン(不透明ポインター)を使用できます。
C ++は組み込みの世界でその地位を占めていると言ってもいいでしょう。あなたはそれをあなたが望むすべてを憎むことができますが、それは消えません。非常に効率的な方法で記述できますが、Cを使用するよりも正しく実行する方法を習得するのは困難です。問題を解決したり、より優れたインターフェイスを表現したりする場合は、Cよりもうまく機能することがありますが、繰り返しになりますが、自分自身を教育し、方法を学ぶことを恐れないでください。
C ++は組み込みシステムに最適です。現在、特定のマイクロプロセッサを使用するかどうかの主要な基準として、優れた開発ツールの有無(またはその欠如)を使用しています。
リソースコストが低いため、組み込みシステムでの使用に適したC ++の領域:
OKエリア:
主に小規模システムでは受け入れられない実行時オーバーヘッドのために、使用しない領域:
foo
通話bar
中try
/ catch
ブロック、およびbar
いくつかのオブジェクトとの通話を作成boz
例外をスローし、システムが何らかの形のオブジェクトのデストラクタを呼び出す必要がありbar
に制御を返す前に作成したがfoo
。例外が完全に無効にbar
されていない限り、例外がboz
スローされる可能性があるかどうかを知る方法がないため、その可能性を考慮して追加のコードを含める必要があります。それに対処するために、「チェックされた例外」を備えたC ++のバリエーションを見たいと思います。例外のエスケープを許可できるルーチンの場合
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の一般的な機能よりも重いものではありません。
16ビットまたは32ビットMCUに移動すると、Cのより重い機能(スタック、ヒープ、ポインター、配列、printfなど)を使用することが理にかなっています。同様に、より強力なMCUが適切になります。 C ++のより重い機能(スタック、ヒープ、参照、STL、新規/削除)を使用する。
そのため、PIC16でC ++を検討する必要はありません。言語とMCUを正しく理解していれば、両方を効果的に併用する方法がわかります。
a[i] = b[j] * c[k];
これらの変数の性質に応じて、約4ページの命令を生成できます。」MCU /コンパイラがこれを行うのは、80年代のガレージ愛好家のCPUを使用しているためです。
私はいつもこれらの議論が楽しく読めると思います。さまざまな利用可能な言語の長所と短所についての知的議論についてはそれほどではありませんが、通常は仕事/経験/関心のある分野に基づいてトピックに関する誰かのスタンスを固定することができます。CSメジャーとメンテナンスプログラマがクヌースを左右に引用し、パフォーマンスが重要な現実の世界で働いている人がすべて狂っていると思うのは、「時期尚早な最適化」の議論があります(私は後者のグループのメンバーです)公平であるために)。
1日の終わりに、CまたはC ++で優れたソフトウェアを開発するか、ここに言語を挿入できます。それは、言語ではなく開発者の能力にかかっています。通常、言語の専門家である必要があるのは、最初に間違った言語を選択し、それを問題解決にワープする必要がある場合のみです。ほとんどの場合、これらは曖昧な機能またはコンパイラーに飛び込む必要がある唯一の状況です目標を達成するためのトリック。
私はよく、これらの議論を「私は言語Xと何とか専門家だ」と始めると聞きます。正直に言って、私はすぐにこれらの人々の信用を失います。ツールを使用して問題を解決し、それがいかに「クール」であるかを示したいという欲求によって。
開発者が最初にツールセットを選択し、次にそれを問題に合わせようとするのをよく見ます。
別の答えへのコメントで述べたように、これらの言語戦争はしばしば、言語Xがプログラマーにもっと馬鹿げたことをさせると主張するようになります。読むのは楽しいですが、これらすべてのステートメントは、あなたが良い開発者を雇う問題を抱えており、悪い開発者を雇い続け、できるだけ少ないことができるようにツールを選択することで状況を支援しようとするのではなく、その問題に直接対処する必要があることを本当に意味します可能な限り損傷します。
私の意見では、優れた開発者は、ソフトウェア開発であれハードウェア開発であれ、問題を調査し、ソリューションを設計し、「最良の方法」でソリューションを表現できるツールを見つけます。必要なツールが以前に使用したことがないものであっても、新しいツールを選択するプロジェクトに3〜4の言語/開発ツールを使用した後は、開発時間に最小限の影響しかありません。
もちろん、「最善の方法」は主観的な用語であり、研究段階でも定義する必要があります。目の前の問題に基づいて、パフォーマンス、表現の容易さ、コード密度など、多くの問題を考慮する必要があります。適切なツールを選択し、問題を理解するために時間を割いて「無料で」提供する必要がある場合は、理由のためにそのリストに保守性を含めませんでした。コードの維持が難しいのは、多くの場合、間違ったツールを選択したか、システム構造が貧弱なためです。これにより、コードを機能させるためのいハックが発生します。
特定の問題を定義することなく、他の言語よりも「良い」と主張するのはばかげています。オブジェクト指向のアプローチは、機能的なアプローチよりも常に優れているとは限りません。オブジェクト指向の設計パラダイムに非常に役立ついくつかの問題があります。そうでないものはたくさんあります。人々がハーピングを楽しんでいると思われる多くの言語機能について同じ声明を出すことができます。
実際にコードを入力する問題に20%以上の時間を費やしている場合は、おそらく非常に貧弱なシステムを開発しているか、非常に貧弱な開発者がいます(またはまだ学習中です)。ほとんどの時間を前もって問題を図式化し、アプリケーションのさまざまな部分がどのように相互作用するかを判断する必要があります。才能のある開発者のグループをマーカーボードと解決すべき問題のある部屋に貼り付けて、システム全体に満足するまでコードの記述やツールの選択を許可しないように伝え、システムの品質を向上させます開発時間の改善が保証された最新の新しいツールを選択するよりも、出力と開発速度が向上します。(スクラム開発を、私の議論とは反対の極の参照として調べてください)
多くの場合、多くの企業は開発者の価値を、書かれた行の数、または「目に見える出力」を見ることによってしか測定できないという現実がしばしばあります。彼らは、マーカーボードがある部屋での3週間を生産性の低下と見なしています。開発者は多くの場合、開発の「思考」段階をスピードアップすることを余儀なくされるか、社内の政治的問題によって設定されたツールを使用せざるを得ません。 。さらに悪いことに、適切な市場調査を行うことができないか、変更が開発サイクルに与える影響を理解していないため、会社から絶えず変化する一連の要件を取得します。
この暴言で少し話題から外れてすみません、私はこの話題について非常に強い意見を持っています。
どの言語でも組み込みシステムに適しています。組み込みとは、無料のコンピューターとは対照的に、より大きな装置の一部を意味します。
(ハード)リアルタイムまたは限られたリソースのシステムを求められたとき、質問はより関連性があります。
リアルタイムシステムの場合、C ++は最も厳しい言語の1つであり、厳しい時間の制約のためにプログラミングする場合に適切です。ヒープの使用(無料の演算子)を除き、実行時間が不定の構造はないため、プログラムがタイミング要件を満たしているかどうかをテストでき、さらに経験を積むと予測することもできます。もちろん、新しい演算子を1回限りの割り当てに使用することはできますが、ヒープの使用は避けてください。C ++がCを介して提供する構成は、組み込みシステム(OO、例外、テンプレート)で有効に使用できます。
非常にリソースに制限のあるシステム(8ビットチップ、数KB未満のRAM、アクセス可能なスタックなし)では、完全なC ++は不適切な場合がありますが、それでも「より良いC」として使用される場合があります。
残念なことに、Adaは一部のニッチでしか使用されていないようです。多くの点でPascal ++ですが、すでに深刻な混乱を招いた言語との上位互換性の負担はありません。(編集:深刻な混乱はもちろん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にとっても問題ですが、アクセスはより明確です。経験則として、基本的にISRコンテキストのネームスペースstdの何も、clibの状態(errornoやヒープなど)にアクセスしないことが確実でない限り使用しないでください。スレッド(私はRTCを好む)を使用してnewとdeleteをオーバーライドし、mallocとfreeへのアクセスを同期する場合にも重要です。
結論として、C ++にはいくつかの問題がありますが、本質的にはすべて修正可能または回避可能です。
Cの場合、問題は高次です。コンパイル時に最適化を実行したり、不変条件をチェックしたりする方法で物事を抽象化するCの構文能力はありません。したがって、ユーザーがそれらを使用するためにそれらがどのように機能するかを知る必要がない方法で物事を適切にカプセル化することはできず、私のエラー検出のほとんどは実行時に行われます(遅すぎるだけでなくコストもかかります)。基本的に、Cでジェネリックにする唯一の方法はデータを使用することです。たとえば、実行時に評価されるフォーマット文字列をprintfまたはscanfに渡します。そのため、コンパイラが正しいデータを渡したときに理論的に可能なオプションの一部を使用していないことを証明するのは非常に困難です。つまり、潜在的なデッドコード生成と最適化の可能性の損失を意味します。
私はここでシットストームを解き放つかもしれないことを知っていますが、32ビットマイクロコントローラでの私の経験は、両方の専門家によって書かれたCとC ++の比較です(C ++は高度にテンプレート化されている可能性があります)C ++はすぐにはるかに効率的な言語ですどんなものでも(ライブラリのように)すべてジェネリックである必要があり、ジェネリックでない場合でも基本的に同等です。また、初心者にとっては、C ++のエキスパートライブラリ実装者の専門知識を活用するのも簡単です。
同時に、実際には、入力がintではなく、誤ったデータを渡すことができない関数が実際にはほとんどありません。 something
表現の方法としてintを使用しているため間違っています(無効な値または「何か」ではなく「otherThing」を渡します)。Cでは、ユーザーが間違っているかどうかを確認する唯一の方法は実行時です。C ++では、すべてのチェックではなく、コンパイル時にいくつかの無料のチェックを実行できます。
結局のところ、Cチームは最も弱いプログラマーと同じくらい強力であることが多く、結果として得られるコードの利点は、マルチプレイヤー1またはパフォーマンスペナルティのいずれかです。これが意味することは、ユニークなデザイン決定のユニークな環境で唯一のユニークなジョブの高いパフォーマンスであるか、複数の環境で使用するのに十分な汎用性があることです(他のマイクロコントローラー、他のメモリ管理戦略、他のレイテンシー対。スループットのトレードオフなど))が固有のパフォーマンスコストがあります。
C ++では、専門家によって物事をカプセル化でき、コンパイル時のコード生成が特定のタスクに適応し、静的チェックによりユーザーがバカなことをゼロコストで実行できない多くの環境で使用できます。ここでは、汎用性と高速性のトレードオフがはるかに少ないため、最終的にコスト対利益の観点から、パフォーマンス、安全性、生産性が向上します。
組み込み用の優れたC ++ライブラリがまだ十分に不足していることは有効な批判です。これにより、C ++コンパイラでほとんどCを使用するという実用的な決定につながる可能性があります。プロジェクトでCのみを使用するという決定は、基本的にはイデオロギーに基づいており、レガシーサポートの必要性や、C ++では実行できるがCでは実行できない非常に厳選された一連の愚かなことを控えるチームの規律がないことを認めている同時に、Cでは保護できないがC ++ではできる、はるかに大きな愚かなことをしないように十分に規律を定めました。
私の経歴: ベル研究所の古いプログラマーのもとでの学校外でのトレーニング。学部研究プロジェクトで2年間、2年間働いています。VB.NETのデータ収集/プロセス制御。VB6でエンタープライズデータベースアプリケーションの作業に1.5年を費やしました。現在、2GBのストレージ、512MBのRAM、500MHz x86 CPUを備えた組み込み PCのプロジェクトに取り組んでいます。同時に実行されるいくつかのアプリは、C ++で記述され、その間にIPCメカニズムがあります。はい、私は若いです。
私の意見: 私が上で書いた環境を考えると、C ++は効果的に機能すると思います。確かに、ハードリアルタイムパフォーマンスは、私が使用しているアプリの要件ではなく、一部の組み込みアプリケーションでは問題になる可能性があります。しかし、私が学んだことは次のとおりです。
C ++はCと根本的に異なります(つまり、C / C ++はありません)。有効なCはすべて有効なC ++ですが、C ++は非常に異なる言語であり、CではなくC ++でプログラムする方法を学習して、あらゆる状況で効果的に使用する必要があります。C ++では、手続き型ではなく、オブジェクト指向でプログラミングする必要があり、2つのハイブリッド(多くの関数を持つ大きなクラス)ではありません。一般に、機能の少ない小さなクラスの作成に焦点を合わせ、すべての小さなクラスを一緒に大きなソリューションに構成する必要があります。私の同僚の一人は、私はオブジェクトで手続き的にプログラムを作成していたことを説明してくれました。よりオブジェクト指向の手法を適用し始めたとき、コードの保守性/可読性が向上したことがわかりました。
C ++は、オブジェクト指向開発の形で追加機能を提供します。これにより、コードを簡素化して読みやすく、保守しやすくすることができます。正直なところ、OOPを実行する際のパフォーマンス/スペース効率の改善方法はあまりないと思います。しかし、OOPは複雑な問題を多くの小さな断片に分割するのに役立つテクニックだと思います。そして、それは、このプロセスの要素であり、無視すべきではないコードで作業している人々にとって役立ちます。
C ++に対する多くの議論は、主に動的メモリ割り当てに関係しています。Cにも同じ問題があります。オブジェクト指向アプリケーションは、動的メモリを使用せずに作成できますが、オブジェクトを使用する利点の1つは、これらを動的に簡単に割り当てることができることです。Cと同じように、メモリリークを減らすためにデータを管理する方法に注意する必要がありますが、RAII手法はこれをC ++で簡単にします(動的メモリをオブジェクトにカプセル化することで自動的に破壊します)。すべてのメモリの場所が重要な一部のアプリケーションでは、これは管理するにはあまりにもワイルドで毛深いかもしれません。
編集:
はい、C ++の問題はコードのフットプリントの増加です。
一部のシステムではバイトをカウントしていますが、その場合、システムの境界に近い実行コストを受け入れなければならないため、Cの開発コストが増加します。
しかし、Cでさえ、適切に設計されたシステムでは、すべてをカプセル化しておく必要があります。適切に設計されたシステムは難しく、C ++はプログラマーに非常に構造化され制御された開発方法の場を提供します。OOPを学習するにはコストがかかります。OOPに切り替える場合は、それを受け入れます。多くの場合、管理者はCを続行し、コストを支払わない方がよいでしょう。切り替えの結果を測定するのは難しいためです。生産性が向上します。組み込みシステムの第一人者であるJack Ganssleによる記事は、こちらをご覧ください。
動的メモリ管理は悪魔です。実際には、悪魔は自動ルーティングであり、動的なメモリ管理はPC上でうまく機能しますが、少なくとも数週間ごとにPCを再起動することを期待できます。組み込みシステムが5年間動作し続けると、動的メモリ管理が本当に台無しになり、実際に失敗し始めることがわかります。Ganssleは、彼の記事でスタックやヒープなどについて説明しています。
C ++には、問題を引き起こしやすく、多くのリソースを使用する傾向があるものがいくつかあります。動的メモリ管理とテンプレートの削除は、C ++のフットプリントをCのフットプリントに近づけるための大きなステップです。これはまだC ++です。優れたC ++を作成するためのメモリ管理またはテンプレート。例外が削除されたことに気づかなかったので、リリースで削除したコードの重要な部分は例外であると考えていますが、その時点まで使用しています。フィールドテストでは、例外がキャッチされたことを通知するメッセージを生成することができます。
Linus Torvaldsによるこの反C ++の暴言は面白いと思いました。
C ++の絶対的な最悪の機能の1つは、多くのことをコンテキスト依存にする方法です-つまり、コードを見ると、ローカルビューは単に何が起こっているかを知るのに十分なコンテキストをほとんど与えないことを意味します。
彼は組み込みシステムの世界についてではなく、Linuxカーネルの開発について語っています。私にとって、関連性はこれに由来します.C ++にはより大きなコンテキストを理解する必要があり、オブジェクトテンプレートのセットを使用することを学ぶことができます。数か月後にコードを更新する必要があるときにそれらを覚えているとは信じていません。
(一方で、Python(C ++ではなく、同じOOPパラダイムを使用)を使用する組み込みデバイスで現在作業を行っていますが、これはまさにその問題を抱えています。私の防御では、PCと呼ばれるほど強力な組み込みシステムです。 10年前。)
賛否両論と決定要因については、他の回答がかなり良いケースになったと思うので、要約していくつかのコメントを追加したいと思います。
小型マイクロコントローラー(8ビット)の場合、方法はありません。あなたは自分自身を傷つけようとしているだけで、利益はなく、あまりにも多くのリソースをあきらめます。
まともなOSを搭載したハイエンドマイクロコントローラー(たとえば、32ビット、RAM、ストレージ用に10メガバイトまたは100メガバイト)では、完全に問題ありません。
質問は次のとおりです。境界はどこですか?
確かなことはわかりませんが、C ++で1 MBのRAMと1 MBのストレージを備えた16ビットuC用のシステムを開発したら、後悔するだけです。はい、うまくいきましたが、私が持っていた余分な仕事は価値がありませんでした。私はそれを適合させ、例外のようなものがリークを発生させないようにしなければなりませんでした(OS + RTLサポートはかなりバグが多く、信頼性がありませんでした)。さらに、OOアプリは通常、多くの小さな割り当てを行い、それらのヒープオーバーヘッドは別の悪夢でした。
その経験を考えると、将来のプロジェクトでは、少なくとも16ビットのシステムで、RAMとストレージ用に少なくとも16 MBのC ++のみを選択すると想定しています。これは任意の制限であり、おそらくアプリケーションの種類、コーディングスタイル、イディオムなどによって異なります。ただし、警告を考えると、同様のアプローチをお勧めします。
組み込みシステムで役立つC ++の機能がいくつかあります。例外など、他にもコストがかかる可能性があり、そのコストが常に明らかになるとは限りません。
私が自分の娘を持っているなら、両方の長所を組み合わせた人気のある言語があり、両方の言語に欠けているいくつかの機能が含まれていました。一部のベンダーはそのような機能をいくつか備えていますが、標準はありません。私が見たいいくつかのこと:
インラインvoid copy_uint32s(uint32_t * dest、const uint32_t * src、__is_const int n) { if(n <= 0)return; else if(n == 1){dest [0] = src [0];} else if(n == 2){dest [0] = src [0]; dest [1] = src [1];} else if(n == 3){dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2];} else if(n == 4){dest [0] = src [0]; dest [1] = src [1]; dest [2] = src [2]; dest [3] = src [3];} else memcpy((void *)dest、(const void *)src、n * sizeof(* src)); }コンパイル時に「n」を評価できる場合、上記のコードはmemcpyを呼び出すよりも効率的ですが、「n」をコンパイル時に評価できない場合、生成されるコードは単純にコードよりもはるかに大きく、遅くなりますmemcpyと呼ばれます。
C ++の父親は組み込み専用バージョンのC ++にはあまり熱心ではないことは知っていますが、Cを使用するだけでかなりの改善が得られると思います。
上記のようなものがあらゆるタイプの標準について検討されているかどうかは誰でも知っていますか?
C ++は複数のプログラミング言語です。
a)「より良い」C b)オブジェクト指向言語c)それは、汎用プログラムを書くことを可能にする言語です
これらの機能はすべて個別に使用できますが、3つの機能を同時に使用すると最良の結果が得られます。それでも、そのうちの1つだけを選択すると、組み込みソフトウェアの品質が向上します。
a)「より良い」C
C ++は強力な型付き言語です。Cよりも強力です。プログラムはこの機能の恩恵を受けます。
一部の人々は、ポインターを恐れています。C ++には参照が含まれています。オーバーロードされた関数。
そして言うに値する:これらの機能はどれも、より大きなプログラムや遅いプログラムでは発生しませんでした。
b)オブジェクト指向言語です
誰かがこの投稿で、マイクロコントローラーで機械を抽象化するのは良い考えではないと言った。違う!組み込み技術者である私たち全員が、C ++のそれとは別のシンタックスで、常にマシンを抽象化してきました。この議論で私が見る問題は、一部のプログラマーがオブジェクトを考えることに慣れていないということです。そのため、OOPの利点が見えません。
マイクロコントローラーの周辺機器を使用する準備ができているときはいつでも、周辺機器はデバイスドライバーの形式で(ユーザー自身またはサードパーティから)抽象化されている可能性があります。前に言ったように、次の例が示すように、そのドライバーは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に紹介しました。もうそれはしません。
Flameコンテンツ
C ++は組み込みシステムに適していますか?
うん C ++は書くのが面倒で、維持するのが面倒です。C +は大丈夫です(一部の機能を使用しないでください)
マイクロコントローラーのC ++?RTOS?トースター?組み込みPC?
繰り返しますが C +はそれほど悪くはありませんが、ADAはそれほど苦痛ではありません(それは本当に何かを言っている)。私のように幸運であれば、組み込みJavaを実行できます。チェックされた配列アクセスとポインター演算なしにより、非常に信頼できるコードが作成されます。組み込みJavaのガベージコレクターは最優先事項ではなく、スコープメモリとオブジェクトの再利用があるため、適切に設計されたコードはGCなしで永遠に実行できます。
OOPはマイクロコントローラーで役立ちますか?
確かです。UARTはオブジェクトです..... DMACはオブジェクトです...
オブジェクト状態マシンは非常に簡単です。
C ++はプログラマーをハードウェアから遠ざけすぎて効率的にしませんか?
PDP-11でない限り、CはCPUではありません。C ++はもともとCのプリプロセッサであったため、Bjarne StroustrupはAT&TでSimulaのシミュレーションが遅いことで笑われることを止めました。C ++はCPUではありません。
Javaバイトコードを実行するMCUを入手してください。Javaのプログラム。Cのみんなで笑います。
ArduinoのC ++(動的メモリ管理、テンプレート、例外なし)を「実際のC ++」と見なすべきですか?
いや。MCU用の世俗的なCコンパイラがすべてそうであるように。
第4に、Embedded JavaまたはEmbedded ADAは標準化されています(ish)。他のすべては悲しみです。
組み込みシステムは、複数のタスク用の汎用コンピューターではなく、特定のタスクを実行するように設計されています。組み込みシステムは、コンピューターのハードウェアとソフトウェアの組み合わせです。Cはすべての現代言語の母です。低レベルですがフルパワーの言語であり、あらゆる種類のハードウェアを扱います。したがって、C / C ++は組み込みシステム用のソフトウェアを開発するための最適な選択肢であり、すべての組み込みシステムで非常に使いやすくなっています。オペレーティングシステムUNIXはCで記述されています。ソフトウェア開発の成功は、特定のプロジェクトに最適な言語を選択することであるため、C / C ++言語が8ビットプロセッサと64ビットプロセッサの両方に適切であることが証明されていることは驚くべきことです; メモリがバイト、キロバイト、メガバイトのシステムで。Cにはプロセッサに依存しないという利点があり、これにより、プログラマは特定のプロセッサアーキテクチャの詳細ではなく、アルゴリズムとアプリケーションに集中できます。ただし、これらの利点の多くは、他の高レベル言語にも同様に適用されます。しかし、C / C ++は、他の多くの言語がほとんど失敗したところで成功しましたか?
<暴言>
C ++はそもそもくだらない言語だと思います。OOPを使用する場合は、Javaプログラムを作成します。直接メモリアクセスは完全に(ab)useの範囲内であるため、C ++はOOPパラダイムを強制しません。
MCUを使用している場合は、おそらく100kB未満のフラッシュメモリについて話しています。メモリを抽象化した言語でプログラミングしたい場合:変数または配列を宣言すると、メモリ、ピリオドが取得されます。malloc(別名C ++の「新しい」キーワード)は、組み込みソフトウェアでの使用をほぼ禁止する必要があります。ただし、まれに、プログラムの起動中に1つの呼び出しが行われる場合があります。
地獄、組み込みプログラミングではCが十分に低レベルではない場合があり、変数をレジスタに割り当てたり、インラインアセンブリを記述して割り込みサービスルーチン(ISR)を強化したりする必要があります。「揮発性」などのキーワードは、理解することが非常に重要になります。オブジェクトレベルではなく、ビットレベルでメモリを操作することに多くの時間を費やしています。
なぜ物事は実際よりも単純だと思うようになりたいのですか?
</ rant>