プロセスが中断されると、メモリリークが発生しますか?

プロセスが中断されると、メモリリークが発生しますか?

いくつかの変数を手動で割り当てるプログラムをc / C ++で生成するとします。その後、プログラムの実行中に割り込み信号(Ctrl-C)を送信します。これらの変数はメモリから解放されますか、それともシステムがシャットダウンするまでスペースを占めますか?

また、手動で割り当てられていない整数を作成したばかりの場合、これらの変数は持続しますか、それともすぐに削除されますか?

割り当てられた変数はそのまま残り、一般変数は(スタックのために)削除されると思います。このような場合、プログラムが停止した後に割り当てられた変数をメモリから解放する方法はありますか?

ただ気になりました。 :)

答え1

プロセスはカーネルによって管理されます。カーネルは、プログラマが変数を割り当てる方法には興味がありません。特定のメモリブロックがプロセスに属することだけを知っています。 C ランタイムは、C メモリ管理機能をカーネル機能と一致させます。自動変数は「スタック」というメモリブロックに入り、ダイナミックストア(mallocおよび友達)は「ヒープ」と呼ばれるメモリブロックに入ります。プロセスは、次のシステムコールを呼び出します。sbrkそしてmmap粒度を次のように取得します。メモリ管理デバイスページ。ランタイムは、これらのブロック内で自動変数と動的に割り当てられたオブジェクトを配置する場所を決定します。

プロセスが終了すると、カーネルはプロセスで使用されなくなった各MMUページを記録するためにメモリ管理テーブルを更新します。これは、独自の違反(システムコール呼び出し)か非違反(信号によって終了)であるか、プロセスが終了する方法に関係なく発生します。どのプロセスでも使用されなくなったページは、再利用可能としてマークされます。

長期実行プログラムでは、コードスニペットをいつ再利用できるかがわからないため、使用されなくなった動的に割り当てられたリポジトリを解放するのが一般的に衛生的です。ただし、プロセスが終了すると、オペレーティングシステムはメモリ、開いているファイルなどのすべてのリソースを解放します。

オペレーティングシステムで自動的にクリーンアップされない唯一のリソースは、一時ファイルなど、オペレーティングシステムのグローバルスコープを持つように設計されたリソースです。

答え2

SIGINTシステムコールは、プロセスが正常に終了するか、等を介して終了するたびに呼び出されます。この呼び出し操作の一部は、プロセスが使用しているリソースを回収することです。デフォルトでは、オペレーティングシステムによって返されたシャットダウンステータス(成功または失敗)を確認するたびに2つのことが発生します。SIGTERMSIGKILLexitexit

  1. SIGCHLD子プロセスが終了したことを親プロセスに通知するために、親プロセスに送信されます。
  2. exit終了したばかりのプロセスで使用されたリソースをクリーンアップするシステムコールを呼び出します。

ゾンビプロセスと孤立プロセスの場合でも、オペレーティングシステムは終了コードをキャプチャするために特別なプロセスを割り当て、システムコールをexit呼び出します。

free()しかし、これがコードでは使用できないという意味ではありません。そうしないと、ソフトウェアのメモリ要件が増加し、システム全体の速度が遅くなります。もう必要ないものはすべてリリースする必要があります。

答え3

一部のメモリビットをクリアする必要がある場合(パスワードや秘密鍵など)、memset(3)プロセスが開始される前に呼び出すか操作を実行するためのシグナルハンドラが必要です。また、見ることができますナトリウムsodium_mlock、ここsodium_memzeroには以下に関連する便利で移植可能なルーチンがあります。カーネルは、各プロセスが終了した後は常にすべてのメモリをゼロにすることができますが、これによりシステムが遅くなる可能性があります。

以前に使用された(ただしゼロではない可能性があります)、メモリは必要に応じてカーネルによって再利用されます。手動メモリ割り当てを提供する言語のプログラマは、データ構造に以前のプログラムの内容を含めることができることを認識する必要があります(-WuninitializedコンパイルされたTheデバイスフラグはここに関連しています)。

すべての割り当てが常にゼロに設定されるというStephenKittの主張については、その仮定に基づいてコードを書くことができるようです。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
    int i, blahblah[1000000];
    for (i = 0; i < 1000000; i++) {
      if (blahblah[i] != 0) {
          printf("whoops, %d at %d ain't zero\n", blahblah[i], i);
      }
    }
    exit(EXIT_SUCCESS);
}

関連情報