2

オブジェクト (変数、関数、構造体など) が c++ でどのように機能するかを理解しようとしています。この場合、それらを格納する方法は基本的に 2 つあります。スタックとヒープです。したがって、ヒープ ストレージが使用されるたびに、手動で割り当て解除する必要がありますが、スタックが使用されている場合は、割り当て解除が自動的に行われます。したがって、私の質問は、悪い習慣がプログラム自体またはコンピューターに引き起こす可能性のある問題の種類に関連しています。例えば:

1.-関数の無限反復を使用して、再帰ソリューションを使用してプログラムを実行するとします。理論的にはプログラムがクラッシュ (スタック オーバーフロー) しますが、コンピューター自体に問題が発生することはありますか? (おそらくRAMまたはSOに)。

2.- ヒープ上のメモリの割り当てを解除するのを忘れるとどうなりますか。つまり、プログラムに問題を引き起こすだけなのか、それともコンピューター全体に永続的なものなのか. というか、そんな記憶は二度と使えない、とか。

3.- セグメンテーション違反 (ヒープ) を取得する際の問題は何ですか。

これに関連する他のいくつかの危険や心配は大歓迎です。

4

4 に答える 4

10

したがって、スタック ストレージが使用されるたびに、手動で割り当て解除する必要がありますが、ヒープが使用されている場合、割り当て解除は自動的に行われます。

スタック (関数内のローカル変数) を使用すると、それらは関数の終了 (戻り) 時に自動的に解放されます。

ヒープから割り当てると、割り当てられたメモリは解放されるまで「使用中」のままになります。そうしないと、プログラムが十分に長く実行され、「もの」を割り当て続けると、使用可能なすべてのメモリが使用され、最終的に失敗します。

アプリケーションで「stackfault」から回復することはほとんど不可能であることに注意してください。これは、スタックがいっぱいになるとスタックが使用できなくなり、「エラーから回復」するためのほとんどの操作にはいくつかのスタック メモリの使用が含まれるためです。通常、プロセッサにはスタック フォールトから回復するための特別なトラップがありますが、それがオペレーティング システムに侵入し、アプリケーションがスタックを使い果たしたと OS が判断した場合、多くの場合、まったく慈悲を示さず、アプリケーションをただちに「強制終了」します。 .

1.-関数の無限反復を使用して、再帰ソリューションを使用してプログラムを実行するとします。理論的にはプログラムがクラッシュ (スタック オーバーフロー) しますが、コンピューター自体に問題が発生することはありますか? (おそらくRAMまたはSOに)。

いいえ、コンピューター自体は、これによって害を受けることはありません。プログラムがユーザーが作業しているものを保存していなかった場合、もちろんデータが失われる可能性があります。

ハードウェアの設計が非常に悪い場合を除き、格納されたデータの損失を超えて、コンピューターに害を及ぼすコードを作成することは非常に困難です (もちろん、最初のセクターから最後のセクターまで、ハード ディスク全体を埋めるプログラムを作成する場合は、あなたのデータは、あなたのプログラムがディスクをいっぱいにするもので上書きされます - これにより、ディスクにオペレーティング システムを再インストールするまで、マシンが再起動しない可能性があります)。しかし、RAM とプロセッサが不適切なコーディングによって損傷を受けることはありません (幸いなことに、ほとんどのプログラマは時々間違いを犯します)。

2.- ヒープ上のメモリの割り当てを解除するのを忘れるとどうなりますか。つまり、プログラムに問題を引き起こすだけなのか、それともコンピューター全体に永続的なものなのか. というか、そんな記憶は二度と使えない、とか。

プログラムが終了したら (そして、「メモリが多すぎる」プログラムのほとんどは何らかの形で終了します)。

もちろん、オペレーティング システムや他のアプリケーションが「使用可能なメモリがまったくない」ことをどの程度うまく処理できるかは、少し異なります。オペレーティング システム自体は一般的に問題ありませんが、不適切に記述された一部のドライバーはクラッシュする可能性があり、運が悪いとシステムが再起動する可能性があります。使用可能なメモリがない場合、割り当ては「返されるアドレス」として NULL (ゼロ) になるため、アプリケーションは十分なメモリがないためにクラッシュする傾向があります。最新のオペレーティング システムでアドレス 0 を使用すると、ほとんどの場合、「セグメンテーション違反」または同様の問題が発生します (詳細については、以下を参照してください)。

しかし、これらは極端なケースであり、ほとんどのシステムは、システムの残りの部分が影響を受ける前に、1 つのアプリケーションが使用可能なすべてのメモリを消費するように設定されています。 OS が単に「多くのメモリを消費する」という理由でアプリケーションを強制終了した場合、最初に強制終了されます。Linux には「メモリ不足キラー」があります。これは、システムが動作し続けることを保証するための非常に抜本的な方法です [「動作」の定義による]。

3.- セグメンテーション違反 (ヒープ) を取得する際の問題は何ですか。

セグメンテーション違反は、ヒープとは直接関係ありません。セグメンテーション違反という用語は、さまざまな用途にメモリの「セグメント」を使用していた古いオペレーティング システム (Unix スタイル) に由来し、「セグメンテーション違反」は、プログラムが割り当てられたセグメントの外に出たときでした。最新のシステムでは、メモリは「ページ」に分割されます - 通常はそれぞれ 4KB ですが、一部のプロセッサはより大きなページを持ち、多くの最新のプロセッサは、たとえば 2MB または 1GB の「ラージ ページ」をサポートし、メモリの大きなチャンクに使用されます。 .

ここで、そこにない (または「自分の」ページではない) ページを指すアドレスを使用すると、セグメンテーション違反が発生します。これにより、通常、その場でアプリケーションが終了します。セグメンテーション違反を「トラップ」することはできますが、私が認識しているすべてのオペレーティング システムでは、この「トラップ」から続行しようとすることは有効ではありません。後で、など。

于 2013-01-16T20:51:20.567 に答える
6

まず、スタック/ヒープの割り当てに関する理解が逆になっています。スタックに割り当てられたデータは、範囲外になると自動的に再利用されます。動的に割り当てられたデータ (newまたはで割り当てられたデータ) は、一般にヒープ割り当てデータであり、 /mallocで手動で再利用する必要があります。ただし、C++ デストラクタ ( RAII ) を使用して、動的に割り当てられたリソースを自動的に再利用できます。deletefree

第二に、あなたが尋ねる 3 つの質問は C++ 言語とは何の関係もありませんが、C++ プログラムを実行する環境/オペレーティング システムに関してのみ回答可能です。最近のオペレーティング システムは通常、プロセスを分離するため、不正なプロセスは実行されません。 t OS メモリまたはその他の実行中のプログラムを踏みにじる。たとえば、Linux では、各プロセスには、カーネルによって割り当てられる独自のアドレス空間があります。不正なプロセスが割り当てられたアドレス空間外のメモリ アドレスに書き込もうとすると、オペレーティング システムは SIGSEGV (セグメンテーション フォールト) を送信し、通常はプロセスを中止します。MS-DOS などの古いオペレーティング システムにはこの保護機能がなかったため、無効なポインターへの書き込みやスタック オーバーフローのトリガーにより、オペレーティング システム全体がクラッシュする可能性がありました。

同様に、ほとんどの主流の最新のオペレーティング システム (Linux/UNIX/Windows など) では、メモリ リーク (動的に割り当てられるが再利用されないデータ) は、それらを割り当てたプロセスにのみ影響します。プロセスが終了すると、プロセスによって割り当てられたすべてのメモリが OS によって回収されます。ただし、これはオペレーティング システムの機能であり、C++ 言語とは関係ありません。一部の古いオペレーティング システムでは、OS であっても、リークしたメモリが再利用されない場合があります。

于 2013-01-16T20:32:48.467 に答える
0

まず、スタックは自動メモリ、ヒープは手動メモリを意味します。両方を回避する方法はありますが、一般的にはより高度な問題です。

  1. 最新のオペレーティング システムでは、アプリケーションはクラッシュしますが、オペレーティング システムとマシン全体は引き続き機能します。もちろん、この規則には例外がありますが、それらは (再び) より高度なトピックです。

  2. ヒープから割り当てて、完了時に割り当てを解除しないということは、メモリを使用していなくても、プログラムがまだメモリを使用していると見なされることを意味します。チェックしないままにしておくと、プログラムはメモリの割り当てに失敗します (メモリ不足エラー)。メモリ不足エラーを処理する方法は、クラッシュ (未処理の例外が発生する未処理のエラーまたは NULL ポインターがアクセスされ、セグメンテーション違反が生成される) から奇妙な動作 (例外がキャッチされるか、NULL ポインターがテストされるが、特別な処理は行われない) まで、あらゆることを意味する可能性があります。ケース) 何もない (適切に処理された)。

最新のオペレーティング システムでは、アプリケーションの終了時にメモリが解放されます。

  1. 通常の意味でのセグメンテーション違反は、単にアプリケーションをクラッシュさせるだけです。オペレーティング システムは、ファイルまたはソケット ハンドルをすぐに閉じる場合があります。また、アプリケーションのメモリのダンプを実行して、そのために設計されたツールを使用して死後にデバッグを試みることができるようにすることもできます (より高度なテーマ)。

あるいは、最近のほとんどの (私が思うに?) オペレーティング システムは、何か悪いことをしたことをプログラムに伝える特別な方法を使用します。その後、プログラムのコードが、それから回復できるかどうか、またはオペレーティング システムの追加のデバッグ情報を追加できるかどうかなどを決定します。

  1. ヒープをスタックのように少し動作させるには、自動ポインタ (スマート ポインタとも呼ばれます) を検討することをお勧めします。最新のコンパイラを使用している場合は、std::unique_ptr を参照してください。その型名が見つからない場合は、boost ライブラリ (google) を調べてください。少し高度ですが、非常に価値のある知識です。

お役に立てれば。

于 2013-01-16T20:55:50.477 に答える
0

1.- Let'suposse that I run a program with a recursion solution by using an infinite iteration of functions. Theoretically the program crashes (stack overflow), but does it cause some trouble to the computer itself? (To the RAM maybe or to the SO).

スタック オーバーフローは、オペレーティング システムにもコンピュータにも問題を引き起こしません。最新の OS はすべて、各プロセスに分離されたアドレス空間を提供します。プロセスが使用可能なスペースよりも多くのデータをスタックに割り当てようとすると、OS はそれを (通常は例外を介して) 検出し、プロセスを終了します。これにより、他のプロセスが影響を受けないことが保証されます。

2.- What happens if I forget to dealocate memory on the heap. I mean, does it just cause trouble to the program or it is permanent to the computer in general. I mean it might be that such memory could not be used never again or something.

プログラムが長時間実行されるプロセスであるかどうか、および割り当て解除に失敗しているデータの量によって異なります。長時間実行されるプロセス (サーバーなど) では、メモリ リークが繰り返されるとスラッシングが発生する可能性があります。しばらくすると、プロセスが大量のメモリを使用し、物理メモリに収まらなくなります。OS は仮想メモリを提供しますが、OS は有用な作業を行うよりも物理メモリからディスクへのメモリ ページの移動に多くの時間を費やすため、これ自体は問題ではありません。これは他のプロセスに影響を与える可能性があり、システムの速度が大幅に低下する可能性があります (システムを再起動したほうがよい場合があります)。

3.- What are the problems of getting a segmentation fault (the heap).

セグメンテーション違反は、プロセスをクラッシュさせます。ヒープの使用に直接関係するのではなく、プロセスに属していないメモリ領域へのアクセスに関係しています (アドレス空間の一部ではないため、または解放されていたため)。プロセスが何をしていたかによっては、これが他の問題を引き起こす可能性があります。たとえば、クラッシュが発生したときにプロセスがファイルに書き込んでいた場合、ファイルが破損する可能性が非常に高くなります。

于 2013-01-16T20:54:15.800 に答える