2017-01-02 2 views
5

一般的にダイナミックアロケーションは許可されず、例外は許可されない安全ソフトウェアを検討してください。動的割り当ては、クラスexplicityが演算子newdeleteを定義している場合にのみ許可されます。オペレータnewを他のクラスに使用すると、コンパイルに失敗します。一方では、標準ライブラリとこの原因の副作用をグローバルオペレータのないベアメタルnew

void* operator new(std::size_t) = delete; 

説明した状況では、コンパイルの失敗を引き起こすための最も簡単な方法は、グローバルnew演算子を削除することです。例えば、<array>を含めると、<new_allocator>に包含され、<stdexcept>となります。 <new_allocator>::new演算子を使用するため、例外とメモリ割り当てを使用しない場合でもビルドに失敗します。 Scoot Meyersによると、<array>は素人フレンドリーでなければなりません。

一方、内蔵オペレータ

src/main.cpp:91:31: error: deleted definition of 'void* operator new(std::size_t)' 
void* operator new(std::size_t) = delete;        ^
<built-in>: note: previous declaration of 'void* operator new(std::size_t)' 

コンパイラでこの原因エラーが::newを禁止して<array>を使用するための任意の解決策はありますか?

グローバルに::newを禁止するソリューションはありますかにすべて

+0

リンク時に少し遅れてエラーが発生してもよろしいですか? –

+0

@Marcビルドにまったく失敗した解決策は大丈夫です。 –

+1

Cにはたぶん良い理由があります。これはそれらの1つのように聞こえる。 Cは隠れたオーバーヘッドを生成しません。 「新」は唯一の問題ではないが、不注意もトラブルにつながる可能性がある。割り込みハンドラやその他のタイムクリティカルなパスの場合 – Olaf

答えて

4

GCCとGNU LDを使用している場合は、--wrap=mallocをリンカフラグに追加することができます。グローバル::newmalloc()を内部で使用しているため、アプリケーション内のmalloc()へのすべての呼び出しは​​に置き換えられます。この関数が未定義の場合、リンクは失敗します。

別の、もっと簡単なオプションは、ASSERT(DEFINED(malloc) == 0, "Dynamic allocation used!");をリンカースクリプトに追加することです。これはmalloc()が定義されていないと主張します。

これらのオプションのいずれも、グローバルな割り当ての他の形式を使用するためにグローバル::newを再定義することを防ぎません。二つのことは、私が強調したいがあります

3

かかわらず、あなたが使用しているもの、プログラミング言語の:

任意のサウンド、ベアメタルシステム上で、あなたは単に完全にリンカスクリプトから.heapセグメントを削除します。動的割り当てに依存しているコードは、リンクできません。とにかく使用しないセグメントにRAMを割り当てる必要はありません。

+4

この解決策は、 'new'や' malloc() 'がこのセクションの存在に依存するプラットフォームでのみ動作します。多くのプラットフォームでは、このセクションは必要なく、newlibをlibcとして使用するすべてのシステムでは、独自の '_sbrk_r()'関数を実装するだけで済みます。この関数は、このセクションとは関係ありません。 –

2

...あなたはリンカスクリプトのグローバルシンボル::newのために同じことを行うことができますが、その名前は、(ここでは_Znwjに)台無しにされているので、これは少し奇妙になります。

  1. 例外に関連するヘッダーをその定義と共に含めると、例外がコードに含まれない場合には気にする必要はありません。
  2. 例外を無効にすると、コード内でその例外を使用することはできません(実行するとコンパイルが失敗します)。ただし、標準ライブラリからの例外の使用は削除されません。標準ライブラリには、std::string(すなわちstd::basic_string<char, ...>)やstd::streambuf(すなわちstd::basic_streambuf<char, ...>)のような、事前にコンパイルされたテンプレートクラスが含まれている場合があります。コードで使用すると、コンパイラはテンプレートのインスタンス化を試みません。例外を含む事前コンパイル済みのバージョン。

コードをもっとよくコントロールするために、G ++コンパイラで-nostdlibコンパイルオプションを使用して標準ライブラリを完全に除外することを強くお勧めします。 STLのstd::arrayのようなさまざまなテンプレートクラスを使用することはできませんが、C++ライブラリとランタイム全体が除外されます。

また、Practical Guide to Bare Metal C++を読むことをお勧めします。これは、C++ベアメタル内部についてより深い洞察を与えるかもしれません。

+1

BTW - item nr 2の正確な理由私はARMマイクロコントローラ用の独自のツールチェーンをコンパイルしました.C++例外はlibstdC++全体で適切に無効になっています - https://github.com/FreddieChopin/bleeding-edge-toolchain –

関連する問題