2

静的メモリに多数のクラスを割り当て、C++ を使用する組み込みプロジェクトにヒープを使用したくありません。現在、静的に割り当てられたクラス専用の別の CPP ファイル内のクラスに対して次のことを行う場合:

Config cfg(spi);

これは、私が知る限り、ヒープに割り当てられます。アセンブリ コードをステップ実行すると、最終的に malloc が呼び出されることがわかります。スタック トレースは次のようになります。

malloc()
__register_exitproc()
__static_initialization_and_destruction_0()
_GLOBAL__sub_I_periodic()
__libc_init_array
<reset vector>

Config クラスは次のようになります。

class Config
{
   public:
      Config(SPIDriver &spi);
      virtual ~Config();
   private:
      SPIDriver *_spi;
}

実装は次のようになります。

Config::Config(SPIDriver &spi)
: _spi(&spi) {}
Config::~Config() {_spi = NULL;}

GCCにこれをヒープではなく静的メモリに配置させる方法はありますか? 前もって感謝します!

4

3 に答える 3

3

私はついに自分の問題を突き止めました。ザックの言うとおり、__register_exitproc が呼び出され、デストラクタがリンク リストに登録されます。これが malloc が呼び出される理由なので、リンクされたリストにスペースを割り当てます。私たちのプログラムは、ベアメタル ARM (Cortex M4) 上で実行されます。したがって、電源を切ると電源が失われるため、クラスが破壊されることはありません。幸いなことに、__register_exitproc は弱い関数なので、何もしないこの関数の別のバージョンを作成しました。動的メモリ割り当てに問題はなく、機能していましたが、__register_exitproc で何らかの理由で、奇妙な (文字通り) アドレスを持つメモリ位置から ARM GPR に 32 ビット値をロードしようとしていました。これにより、Hard Fault 例外がスローされます。__register_exirproc をオーバーライドすることで、この例外の発生を防ぎます。

これが他の誰かに役立つことを願っています。いつものように、ありがとうまたは助けて!!!

于 2013-01-30T15:47:48.687 に答える
2

あなたの混乱はすべて、cfgがヒープに割り当てられているかどうかわからないという事実から来ています。起動時にどこかで malloc を呼び出すだけでは意味がありません。libc は、void プログラムに対しても malloc を数回呼び出します。

データの場所を特定する方法を説明しましょう。

コードから始めましょう。いくつかは変更されています。

#include "stdlib.h"

class Config
{
   public:
     Config(int spi) {_spi = &spi;}
     virtual ~Config() {;}
   private:
     int *_spi;
};

Config cfg(2);

int
main(void)
{
  int *x = new int(2);
  return 0;
}

コンパイルしてみましょうg++ -g -O0 statstorage.cpp -static

.out ファイルを取得しました。次に、データが実際にどこにあるかを確認する必要があります。まず、次のようなコマンド ラインで gdb を呼び出します。

echo -e "start\nstep\np/x &cfg\np/x x\nquit" > .gdbinit && gdb a.out

次のような出力が得られます。

$1 = 0x6add50
$2 = 0x6c5670

0x6add50 は cfg のアドレス、0x6c5670 は動的に割り当てられた x ポインターのアドレスです。

次のように readelf を呼び出しましょうreadelf -S a.out

そして、セクションがどこにあるか見てください。出力は(私のPCの場合)38セクションです。必要なのは Address フィールドと Size フィールドだけです。私は持っている:

                                Address               Size
[23] .bss              ...  00000000006add00 ... 0000000000014d38
[24] __libc_freeres_pt ...  00000000006c2a38 ... 0000000000000030

__libc_freeres_pt は、null 以外の最大アドレスを持つ最後のセクションです。

0x6c5670 はロードされたバイナリの外側 (ヒープ自体) にあり、cfg は bss セクションの内側にあることがわかります。

これにより、cfg静的に割り当てられたことがわかります。

于 2013-01-30T07:03:50.927 に答える
0

malloc [および関連するガビン]を「取得」していない場合は、独自のグローバルな新しい関数を実装し、たとえば、大量のcharを「ヒープ」として使用する必要があります。

これは、独自の新規/削除関数を作成する方法を説明する前の質問です。また、Cスタイルの割り当てで同じことを実現するためのa関数mallocと関数を記述できる必要があります。free

もちろん、別の方法は、glibcまたは使用しているライブラリがどのように機能するかを書き直すことです。あなたが本当に単純なことだけをしているなら、オプションかもしれません。しかし、遅かれ早かれ動的な割り当てが必要になると思います。そのため、独自に作成する[または既存のものを適応させる]のが最善の選択だと思います。

于 2013-01-29T17:14:00.400 に答える