C++プログラムでは、クラスに対して、静的に作成され動的に作成されるアクティブなオブジェクトの数のカウントをどのように取得できますか?C++でのオブジェクトの静的および動的メモリ割り当て
答えて
悲しいことに、あなたはできません。スコット・メイヤーの本の中には、これを達成しようとするときの課題について説明している部分がありますが、それは不可能です。
より効果的なC++ - Item#27:ヒープベースのオブジェクトの必要性または禁止。
[OK]を、ここで簡単に実証されている問題の一つです(ここで問題になっている項目は複数のページが長いので、私はそれのすべてを要約しませんですが、だ少なくとも一つの挑戦):
多くの(すべてではありません)システムは、以下の方法で自分のメモリを手配:
----------------
| Stack |
| (Grows Down) |
| |
----------------
| |
| |
| |
| |
| |
| |
----------------
| Heap |
| (Grows Up) |
| |
----------------
今、あなたはあなたがヒープか右にしているかどうかを把握するオペレータ新しい/ new演算子と巧妙な何かを行うことができ、このようなメモリ配置に思うかもしれません(あなたが特定のメモリ位置の上か下かをチェックすることによって)?ここに問題がある。静的オブジェクトが移動する場所はシステムによって異なりますので、次のようになります。
----------------
| Stack |
| (Grows Down) |
| |
----------------
| |
| |
| |
| |
| |
| |
----------------
| Heap |
| (Grows Up) |
| |
----------------
| Static |
| Objects |
----------------
これで、静的オブジェクトとヒープオブジェクトを区別できなくなりました。おっとっと!また、私はこれがシステムに依存していると言いました。つまり、それらを区別する方法を見つけたとしても、あなたのコードは移植性がありません。
警告:これは以下に説明するように、「未定義の動作」を使用しています - MOSTプラットフォームで動作することが知られています(Windows、Linux、Symbian OSではARMおよびx86で十分です。 「フラット」メモリモデルを使用するほとんどのOSで)。
自分自身を特定のシステムに「限定」すると、this
と「スタックがある場所」(そして必要な場合は静的データがある場所)の既知の範囲を比較することができます。 [スタックが任意のスレッドのどこにあるのか把握することは可能ですが、少し難しくなります]。静的データの知識を用いて
、およびスタックが配置されている、我々はスタックがどこにあるか、あなたが実際に何とか把握できる場合にのみ動作すること
char *this_addr = static_cast<char*>(this);
if (this_addr >= globa_start && this_addr <= global_end)
globals++;
else if (this_addr >= stacK_top && this_addr >= stack_base)
stacked++;
else heaped++;
注比較することができます - そしてもちろん、それはだが定義されていない振る舞いを持っているため、this
は割り当てられたブロックの外のものと比較されるので、技術的には全体の概念は未定義です。しかし、これはほとんどのOS /プロセッサー・アーキテクチャーで可能です。 [もちろん、デストラクタでも同じことをする必要がありますが、逆にする必要があります]。また、オブジェクトを作成したスレッドとは別のスレッドからオブジェクトを破棄すると、 "楽しい"状態になります)。
編集:与えられたスレッドのスタックを見つけることはそれほど難しくありません。複数のスレッドが存在する]] "最初の関数"(スレッド作成呼び出しに渡されたもの)のローカル変数のアドレス。次に、現在のスレッドの変数のアドレスを取得します。これらの値の間にあるものは、そのスレッドスタックにあります。スタックは連続した1つのメモリの一塊であるためです。
好奇心のために、64ビットで動作するでしょうか(charにキャストしても問題ありません)? –
これは 'char *'であることを意味していました。 –
アクティブなオブジェクトの数を追跡するための最も簡単な解決策は、トレースしたいクラスで
(のgetSize()関数または任意で)オブジェクトマネージャを作成することで、あなたはまた、静的プロパティを追加することができましたコンストラクタとデストラクタでそれぞれ増減します。あなたが個別にこれらの数字を取得することができるようになりますオブジェクトマネージャ(動的割り当て)の大きさと静的プロパティ(すべての割り当て)で
。オプションとして
OPは、動的に割り当てられたオブジェクトと静的に割り当てられたオブジェクトを区別したいと考えています。 – Borgleader
動的割り当ての数とすべての割り当てで、静的割り当ての数を簡単に計算できます。 これは素晴らしいシステムではありませんが、それは私が現時点で考えることができる最も簡単なものです:) – Rak
は、あなたが世界的に新しい過負荷および/デクリメント動的に割り当てられたオブジェクトのグローバルカウントを与えるいくつかの静的なカウンタをインクリメントする削除することができます...
全体の難しさは、静的と動的割り当てを区別することです。どのようにすればいいのか説明してください。 – Borgleader
はい、私はまだ答えはありません...ちょうどカウント(および適切な過負荷の各オブジェクトのサイズ)を取得する方法を説明するために過負荷の可能性を言及したかっただけでなく、これもシステムに依存しないでください。 –
@Borgleaderここでは、これが許容可能な解決策ではないというヒントはありません。また、他の人が指摘しているように、未定義の動作を引き起こさずにこれを行う方法はありません。さらに、メモリリークや何かを解決しようとしているのでなければ、これを行う唯一の正しい解決策だと思います。その場合はvalgrindのような適切なツールを使用する必要があります。より詳細な解決策については私の答えをご覧ください。 – Fozi
あなたは、単にに関する引数を渡すことで、クラスを言うことができますその場所:
class LocationAware {
public:
enum Location { STATIC, STACK, HEAP };
explicit LocationAware(Location location) : my_location(location) {
switch(location) {
case STATIC: ++static_instaces; break;
case STACK: ++stack_instances; break;
case HEAP: ++heap_instances; break;
}
}
~LocationAware() {
switch(my_location) {
case STATIC: --static_instaces; break;
case STACK: --stack_instances; break;
case HEAP: --heap_instances; break;
}
}
private:
const Location my_location;
public:
static unsigned static_instaces;
static unsigned heap_instances;
static unsigned stack_instances;
};
unsigned LocationAware::static_instaces = 0;
unsigned LocationAware::heap_instances = 0;
unsigned LocationAware::stack_instances = 0;
LocationAware stat(LocationAware::STATIC);
int main() {
LocationAware stack(LocationAware::STACK);
LocationAware * heap = new LocationAware(LocationAware::HEAP);
}
もちろんこのクラスに嘘をつくことができます。しないでください。
また、テンプレートを作成して継承やカプセル化を使用し、クラスから使用することができます。
template<class Tag>
LocationAware;
次に、クラス内の場所を継承または保持して初期化します。インスタンスはLocationAware<YourClassOrTag>::xy_instances
を使用して確認できます。
- 1. Cおよびメモリアクセスレイテンシでの連続的なメモリ割り当て
- 2. C++の動的割り当てメモリ内での動的メモリ割り当て
- 3. 自動/静的なメモリ割り当て
- 4. Cでの動的メモリ割り当て
- 5. ネットワークI/OとC++用のバッファの動的なメモリ割り当てと静的なメモリの割り当て
- 6. 静的データ型のメモリ割り当て
- 7. 静的対動的CUDA共有メモリ割り当てのパフォーマンス
- 8. C++動的メモリ割り当て
- 9. ツリーアルゴリズムにおけるメモリの動的割り当てと再割り当て
- 10. KVMの動的メモリ割り当て
- 11. ベクトル<>動的割り当ての代わりに静的メモリ
- 12. C++でのベクトルの動的メモリ割り当て
- 13. 静的割り当てと動的割り当てとの比較自動割り当て
- 14. .netの非静的クラスの静的変数のメモリ割り当て
- 15. Javaでは、静的メモリ割り当てと動的メモリ割り当ての両方でオブジェクトを作成できますか?
- 16. calloc、malloc、および動的構造体割り当て
- 17. 動的割り当て - メモリ管理
- 18. realloc、動的メモリ割り当て
- 19. 2D動的メモリ割り当て - ObjectiveC
- 20. Java動的メモリ割り当て
- 21. Cでの動的割り当てエラー
- 22. 動的なメモリ割り当てのC++文字列
- 23. [C]構造の動的割り当てメモリ、GTK
- 24. 静的および動的バインド
- 25. RDSパラメータグループ - 動的および静的
- 26. 静的および動的MFCリンク
- 27. 静的および動的タイプ
- 28. MapViewOfFileを使用した静的共有メモリの割り当て
- 29. C:スキャン中の動的割り当て
- 30. 構造体c動的にメモリを割り当てます
難易度についてさらに教えてもらえますか? – hivert
私はそれらを今見ています。私は心からそれらを知らない。 – Borgleader
@hivert:基本的な難しさは、言語によってオブジェクトがどのように割り当てられたかを伝えることができないということです。あなたは、スマートポインタまたは "operator new/delete"のオーバーロードを使って動的オブジェクトを追跡することができます。静的、自動、スレッドローカルおよび一時オブジェクトを区別する方法はありません。 –