3

ポインターをインクリメントできることがわかったとき、c で少し遊んでみました。だから、このプログラムで RAM をクリアできるかどうか試してみませんか。

#include <stdio.h>

int main()
{
    int number = 0;
    int *pointer = &number;
    while (true) {
        pointer++;
        *pointer = 0;
    }
    return 0;
}

これが私のオペレーティング システムで機能しない理由ですか、それとも C 言語には例外がありますか?

前もって感謝します!

4

5 に答える 5

3

最新のオペレーティングシステムでは、すべてのプロセスに独自のアドレス空間があります。その中に、独自の実行可能コードとデータがあります。したがって、単に「コンピュータのRAM」にアクセスすることはできません。あなたができることはあなたのプログラムのアドレス空間で物事を台無しにすることです。

次のコードを並行して実行すると、これを簡単に確認できます。

int main()
{
    int i=0;
    printf("The address of i = %p\n",&i);
    sleep(60);
}

(おそらく)すべてのプロセスが同じメモリアドレスを出力することがわかります。もちろん、それらはメモリの同じ物理ビットを指していません。

ps。共有ライブラリ( "DLL")がロードされると、すべてのプロセスがメモリ内の同じ物理ビットを指すようになります。これにより、すべてのプロセスに対して一度だけ多くの実行可能コードをロードする必要があります。これが読み取られます。 -メモリのみであるため、同じライブラリを使用する他のプロセスの実行可能コードを変更できるプロセスはありません。その背後にあるメカニズムはメモリマッピングと呼ばれます。詳細については、mmap()システム呼び出しを参照してください。)

于 2012-09-18T23:00:23.747 に答える
3

これが私のオペレーティング システムで機能しない理由ですか、それとも C 言語には例外がありますか?

言語に関する限り、これは未定義の動作です。所有していないメモリをいじったときに何が起こるかを決定するのは、OS 次第です。

sizeof intにバイトを割り当てnumber、そのアドレスをポインターに格納し、明らかな問題が発生するまで、そのメモリ ブロックを通過し続けます。インクリメントしてその場所に書き込むとすぐに、pointer未定義の動作が呼び出されます。

ランダムなメモリ位置を好きなように読み書きすることはできません (そうすることができますが、プログラムが特定の方法で動作することが保証されていません)。

于 2012-09-18T22:57:29.447 に答える
2

numberはスタック上で宣言されており、スタックとそれに続くメモリ位置を消去しています。つまり、スタックが破損しています。これにより、プログラムがクラッシュする場合としない場合があります。それは未定義の振る舞いです。スタックが破損すると、関数が悪影響を与えることなく正常に終了したように見える可能性がありますが、プロセスが無効なメモリ位置にアクセスしようとすると、SEGVが発生する可能性が高くなります。

于 2012-09-18T22:59:00.973 に答える
1

メモリ保護と呼ばれるものは、これを行うことを防ぎます。基本的に、OSは、割り当てられていないRAMの部分を変更しようとすると、プログラムを終了します。これは、一般にセグメンテーション違反として知られています。

これは、(理論的には)プログラムが特権モードで実行されている場合(デバイスドライバーの作成時やベアメタル組み込みシステムのプログラミング時など)に実行できます。

于 2012-09-18T22:59:00.740 に答える
1

他の人がすでに言ったことをバックアップするために、無効または違法なメモリ位置に書き込むと、プログラムがセグメンテーション違反を引き起こす可能性が最も高くなります。

ランダムなメモリアドレスの内容を更新するためにこれが起こっていることを確認するために、GDB で実行されているプログラムを示します。

[jrn@localhost SO]$ gcc -ggdb dumb.c 
[jrn@localhost SO]$ gdb ./a.out 
GNU gdb (GDB) CentOS (7.0.1-42.el5.centos)
Reading symbols from /home/jrn/source/SO/a.out...done.
(gdb) run
Starting program: /home/jrn/source/SO/a.out 

Program received signal SIGSEGV, Segmentation fault.
0x08048399 in main () at dumb.c:9
9               *pointer = 0;
(gdb) list
4       {
5           int number = 0;
6           int *pointer = &number;
7           while (1) {
8               pointer++;
9               *pointer = 0;
10          }
11          return 0;
12      }
13

9 行目で、あるべきではないメモリ アドレスに書き込んでいるときにエラーが発生することがわかります。OS は、多くの場合 CPU によって提供されるメモリ保護を使用して、誤った書き込みを検出しています。

于 2012-09-18T23:10:04.127 に答える