7

Cが見事にクラッシュする可能性があるとよく耳にします。最近、文字列を返すことを期待していた関数が小さな幸せそうな顔を返すときに、これを初めて味わいました。それ以来、ポインタの初期化と配列のメモリの割り当てにもっと注意を払っています。それでも、プログラムがひどくクラッシュする可能性があるとは信じられません...

プログラムの範囲にもよると思いますが?つまり、ファンを処理するプログラムのバグが、幸せそうな顔をメモリ内の重要なスペースにコピーした場合...?

私の質問は、壮大なCクラッシュの世界には、どれほどの神話があるのか​​ということです。避けるべき危険なことの具体例をいくつか入手できますか?

z。

4

20 に答える 20

17

他のプロセスのメモリをゴミ箱に捨てることができたのは、仮想メモリ以前の時代にはおそらくもっとひどいことだったと思いますが、最近起こりうる最悪の事態は、実際には自分のプログラムをクラッシュさせることです。通常、不良ポインタからのセグメンテーション違反を介して。

もちろん、システムリソースを悪用して物事を爆破することは除外されます。これは、どの言語でも実行できます。

于 2009-03-12T21:21:58.657 に答える
12

私が C++ のプログラミングを学んでいた頃は、システム 7 または 8 を実行している Mac でした。どちらを覚えていません。とにかく、保護された仮想メモリがなかったため、ダングリング ポインターやバッファ オーバーランを残すなどの多くのミスにより、コンピューター全体がクラッシュしました。Apple が Macworld か何かでメモリ空間を保護する新しい OS を作成するつもりであると最初に発表したとき、彼らはプログラムのソース コードを示したのを思い出します。

while (true)
  *(int *)i++ = 1;

そして、彼らがプログラムを実行し、マシン全体ではなくプログラムだけが終了したとき (「コンピューターを再起動する必要はありません」などのメッセージが表示された)、開発者でいっぱいの部屋全体が明らかに拍手喝采しました。いずれにせよ、明らかに保護されたメモリがないと、クラッシュの深刻度が増すため、C や C++ のプログラミングが本当に難しくなります。

最近では、スーパーバイザー レベルで実行するものをプログラミングしていない限り、それほど大したことではありません。OS をクラッシュさせることはできません。

于 2009-03-12T21:30:46.343 に答える
10

私に起こった最悪の事態は、すぐにはクラッシュを引き起こさなかったメモリの破損でしたが、しばらくすると..検出が非常に困難になりました..argh

于 2009-03-12T21:23:12.587 に答える
8

オペレーティング システムは、最近の最も恐ろしい問題を防ぎます。私がこれまでにした最悪のことは、マシンをハードロックし (電源ボタンを押したままにして再起動する必要がありました)、いくつかのファイルをスクランブルすることです。

すべては、実際にアクセスしているリソースに依存します。ファイルを書き込んでいる場合、以前はシステム ユーティリティを混乱させていたディレクトリ構造が複雑になるいくつかの方法がありますが、それらの問題のほとんどは修正されています。root として何かをしている場合は、より多くのシステム ファイルが書き込み可能であるため、確実に混乱する可能性があります。ネットワークを使用している場合、適度にうまくいかない可能性のあるものがたくさんありますが、帯域幅を使いすぎる可能性が高い以上のものではありません. もちろん、数年間のプログラミングで、あらゆる種類のありそうもないことがわかるでしょう。

ただし、ほとんどの場合、実験して遊んでも問題ありません。最近のシステムは十分に回復力があるので、元に戻すのが難しすぎる混乱を起こすことはありません。オペレーティングシステムは、各プログラムを独自のメモリに保持し、管理者/ルートでない限り、重要なシステムを変更するためのアクセスを許可しません. さまざまなぶら下がっているポインターは、面白いものを出力したり、プログラムをクラッシュさせたりするかもしれませんが、最新のコンピューターを破壊することはありません。

別の返信のコメントから: 「ニンテンドー DS を使用して実行しています」

わかりました、それは重要です! (最初: すばらしいアイデア! 面白そうです。) そのようなもののコーディングは、デスクトップ コンピューターのほとんどのコーディングと同じではありません。libnds のドキュメントとニンテンドー DS プログラミングに関するいくつかのチュートリアルを簡単に見てみると、言及すべき OS がないことがわかります。ですから、迷子のポインターでどれだけのことができるかわかりません。おそらくたくさんのことです。おそらく何かを傷つけます。以前にそのプラットフォームでプログラミングを行ったことがある人を探して、彼らの意見を聞くのは良い考えかもしれません。

于 2009-03-12T21:37:48.090 に答える
6

以下は、Henry Spencer の「C プログラマーのための 10 の戒め」からの抜粋です。

  • 戒め 2 - NULL ポインターをたどってはなりません。最後には混沌と狂気が待ち受けています。
  • ヌル ポインターの概念とマクロ NULL (これにはさらに別の意味があります) との間の混乱を最小限に抑えるために、単語は「ヌル ポインター」であるべきだったので、明らかに聖典はここで誤って転記されました。そうでなければ、意味は明白です。ヌル ポインターは、ドラゴン、デーモン、コア ダンプ、およびその他の無数の汚れたクリーチャーで満たされた領域を指します。敬虔にこれを想定している冒涜的な古いコードにもかかわらず、ヌルポインタはどの型の 0 も指しません。

C に慣れていない人のために、C の簡潔な紹介が最もよく書かれているのは、Henry Spencer による「C プログラマーのための 10 の戒め (注釈付き版) 」であると思います。それが書かれている方法は、読者にCの危険性を実際に伝えます...同時に面白いです(これは、読者が実際にもっと注意を払うことを意味します)。

=========================

個人的には...セグフォールトの贅沢があるため、デスクトップ開発を行っているときにCがそれほどひどくクラッシュすることはありません。Seg-faults は、OS があなたが本当に F ' をしようとしているのを見て、「ねえ! あなたはそこでは許可されていません」と言ってプロセスを停止するときです。

組み込み C 開発を行っているとき...それは、本当に素晴らしいクレイジーなものを手に入れるときです...つまり、99.9% の時間で電源を入れ直す必要があります。コードがどういうわけか私の呼び出しスタックを台無しにするこの 1 つの時間のように...そして、あなたはいくつかのランダムな他の関数を実行しています...そして ISR はどういうわけかまだ進行中です...そしてそのようなバグを修正するのに 2 週間かかります.

于 2009-03-12T21:39:53.763 に答える
5

カーネルコードを書いている場合、割り込みベクトル、グローバル記述子テーブル、プロセステーブルなど、システムに不可欠なメモリのビットを上書きして、あらゆる種類の楽しいものを引き起こすことがあります。

于 2009-03-12T21:23:13.757 に答える
5

C自体は何もクラッシュできません。ずさんなプログラミングはすべてをクラッシュさせる可能性があります。

「幸せそうな顔」は、コードがメモリを破壊したことを示しています。Cがそれと関係があったのは、あなたがそれを使用することを選択したという事実だけです。(そして、あなたのOSがそれを可能にしたという事実は驚くべきことです-あなたはまだDOSのバージョンを実行していますか?)

于 2009-03-12T21:26:01.893 に答える
3

最近では、Cをそれほど難しくするのは難しいです(OSカーネルなどをコーディングしている場合を除く)。

DOS / Win95 / Win98の時代に戻ると、Cプログラムを本当にひどくシャッシュにすることができました。私はこれをたくさん手に入れていました:

危険なポインタ操作でメモリが混乱するたびに、さまざまな色のさまざまな文字でいっぱいの文字ベースの画面が表示され、そのうちのいくつかは点滅していました!!! どういうわけか、操作がビデオメモリを台無しにしたと思います。

しかし、今日、プロセスは安全なカーネル内で実行されるため、プロセスがなくなると最悪の事態になります。

于 2009-03-12T21:25:30.613 に答える
2

保護メモリ アーキテクチャ以前は、オペレーティング システムで使用されるジャンプ ベクトルのほとんどは、メモリのゼロ ページ (ゼロから始まるアドレス) に格納されていました。

そのため、ゼロ ページのメモリ位置への書き込み (ヌル/不良ポインターを使用して簡単に実行) は、オペレーティング システムのジャンプ ベクトルを変更し、あらゆる種類の奇妙なクラッシュ動作を引き起こします。ロックアウトされたキーボードやゴミでいっぱいのビデオ画面の点滅からハード ドライブまで、あらゆる種類の異常なクラッシュ動作が発生します。光の点滅狂​​乱、死のブルー スクリーン、再起動など。

【アセンブリ言語でのコーディングがさらに楽しくなりました】

于 2009-03-13T05:00:10.133 に答える
1

コードがリモートで最新のOSで実行されている場合、幸せそうな顔をメモリ内のランダムなポイントにコピーすることはできません。必要なだけクラッシュする可能性があり、その結果、プロセスが終了します。

実際にシステムを台無しにするのに最も近いのは、プロセッサ/メモリ/ディスクリソースを悪用するか、OSがPIDを使い果たすほど多くのサブプロセスを生成することです(それらを格納するために32ビット値を使用している場合)。

于 2009-03-12T21:23:55.377 に答える
1

Commodore PET 4032 (別名 "Fat 40") というコンピューターがありました。メモリの間違った部分に間違った値を突っ込むと、実際にはビデオ チップが完全に焼き尽くされる可能性がありました。そのマシンに C コンパイラがあった場合、ワイルド ポインターが実際にコンピューターに回復不能な物理的損傷を与える可能性があることは想像に難くありません。

于 2009-03-12T21:31:36.840 に答える
1

DOS の時代には、私は実際に BIOS 情報を上書きしました。修理するには技術が必要でした。私の最初のホーム コンピューター - 286。1、2 日後に起動できなくなります。

于 2009-03-12T23:24:10.550 に答える
1

メモリが保護されている OS では、プロセスがクラッシュするという最悪の事態が発生する可能性があります。プロセスがたまたまカーネルまたはカーネル拡張の一部である場合、明らかに OS 全体をクラッシュさせる可能性がありますが、それは最悪の場合です。

ただし、これは実際には他の多くの言語でも同じです (たとえば、C では null ポインターを参照し、Java では null に設定されたオブジェクト参照を使用すると、どちらもプロセスがクラッシュします)。

したがって、保護されたメモリを使用すると、Cは他のどの言語よりも大きなダメージを与えることはできないと思います(プロセスがOSの一部でない限り;))

于 2009-03-13T04:24:12.807 に答える
0

私がWin98ドライバを書いていたとき、BSODはみんなを悩ませていました。私が犯した次の間違いを覚えています

typedef struct _SOME_TAG_ {

    int nSomeVar;
    int nSomeMore;
    ...

} MYSTRUCT、* PMYSTRUCT;

.... PMYSTRUCT pMyStruct;

//そして、メモリを割り当てずにこの構造を使用します;-) pMyStruct-> nSomeVar = 0;

そして、ドライバーのクラッシュはとてもひどいものでしたが、NumegaのSoftICEがありました。たった10年前ですが..昔のように感じます

于 2009-03-13T04:12:22.307 に答える
0

問題のソフトウェアが PC で実行されている場合、「単に」コンピュータがダウンする可能性があります。

しかし、それがあなたの車のエンジンの動作を制御している場合、またはさらに悪いことにABSを制御している場合、クラッシュするのはソフトウェアだけではありません.

于 2009-03-13T17:41:16.793 に答える
0

クラッシュは起こりうる最悪の事態ではありません。

fclose からの戻り値をチェックしない古い Unix ファイル圧縮プログラム (Zip など) について読みました。はい、fclose はエラーを返す可能性があります。ファイルへの出力は通常バッファリングされるため、fwrite または putc の呼び出しが機能しているように見え、OK が返されたとしても、データはまだバッファ内にあり、書き込まれるのを待っている可能性があります。fclose が呼び出されると、書き込まれていないデータはすべてフラッシュされますが、(たとえば) ディスクがいっぱいになる可能性があるため、これは失敗する可能性があります。また、圧縮プログラムは通常、ディスクがほぼいっぱいになったときに実行されるため、これはかなり頻繁に発生しました。そのため、プログラムは静かに新しい圧縮ファイルを切り捨て、元の圧縮されていないファイルは削除され、翌年かそこらで誰かがファイルを解凍しようとしたときに、末尾がありませんでした!

これは、例外をスローすることが良いことである理由の良い例だと思います。

于 2009-03-17T16:36:21.340 に答える
0

さて、DOS の時代にさかのぼると、ブート セクタの一部を上書きすることができました。「OS が見つかりません」などのメッセージを見つけるために再起動するようなものではありませんでした。

その後、非常に慎重にディスクに書き込むという難しい方法を学びます...

于 2009-03-12T22:13:53.010 に答える
0

大学時代、私はマルチスレッド プロキシの作成を任されていました。

ときどき、プロキシは、ページがプルしたリソースのいずれにも応答しませんでした。問題の原因となっているコード:

ファイル ハンドラーの近くで変数を使用する、オーバーフローの問題がある一部のコード。何が起こっているのかを知る前に、ファイル ハンドラの宣言を移動することで問題が「修正」されたことは、本当に奇妙であることがわかりました (笑)。

Ps。これをチェックしてください(Cではありませんが、良い話です:)):http://trixter.wordpress.com/2006/02/02/computing-myth-1-software-cannot-damage-hardware/

于 2009-03-13T05:03:49.703 に答える
0

C を使用すると、マシンを非常に直接的に扱うことができます。どれだけ壮観にクラッシュできるかは、マシンができることの関数です。

つまり、最新の優れたオペレーティング システムで特別な権限を持たないユーザー モード プロセスでは、実際にはそれほど多くのことはできません。しかし、ソフトウェアはいたるところにあります。電車のブレーキ システムを制御するソフトウェアについて考えてみましょう。誰かが本当に助けを必要としているときに緊急インターホンを実行するソフトウェアについて考えてみてください。交通量の多い高速道路で標識を実行するソフトウェアについて考えてみてください。誘導ミサイル システムを実行するソフトウェアについて考えてみましょう。

最近は至る所にソフトウェアがあります。多くはC言語で書かれています。

于 2009-03-12T23:36:18.647 に答える