3

最近、Cプログラムの1つに指摘されました。メモリブロックの開始アドレスが十分に低い場合、ゼロをラップした結果、テストの1つが失敗し、クラッシュが発生します。

最初は「これは厄介な潜在的なバグだ」と思っていましたが、その後、疑問に思いました。このケースは発生する可能性がありますか?私はそれを見たことがありません。公平を期すために、このプログラムはすでに無数のシステムで何百万回も実行されており、これまでに発生したことはありません。

したがって、私の質問は次のとおりです。呼び出しmalloc()が返す可能性のある最小のメモリアドレスは何ですか?私の知る限り、たとえば0x00000032などのアドレスは見たことがありません。

Linux、BSD、Windowsなどの「最新の」環境にのみ興味があります。このコードは、C64や趣味/研究用OSで実行するためのものではありません。

4

3 に答える 3

8

まず第一に、それはあなたが求めていたものなので、私は現代のシステムだけを検討するつもりです。つまり、ページングされたメモリを使用しており、nullポインタの逆参照を処理するために0に障害のあるページがあります。

現在、実際のシステムで私が知っている最小のページサイズは4k(4096バイト)です。つまり、0x1000未満の有効なアドレスはありません。それより低いものは、ゼロアドレスを含むページの一部であるため、nullポインタの間接参照障害が発生することはありません。

現実の世界では、優れたシステムは実際にあなたがそれほど低くなるのを防ぎます。最近のLinuxは、アプリケーションが構成可能なデフォルト(64k、私は信じています)より下のページを意図的にマッピングすることさえ防ぎます。アイデアは、nullポインター(たとえば、nullポインターp[n]が発生する場所p)から障害までの適度に大きなオフセットが必要なことです(Linuxの場合、カーネルスペースのコードがそのようなアドレスにアクセスしようとすると障害が発生することを回避しますカーネルのnullポインタ-特権昇格の脆弱性につながる可能性のある逆参照のバグ)。

そうは言っても、ポインタが指す配列の境界の外でポインタ演算を実行することは未定義の動作です。アドレスが折り返されていなくても、未定義の動作によってプログラムが破損する可能性がある場合、コンパイラが(コードを強化するため、または単に最適化するために)行う可能性のあるあらゆる種類のことがあります。優れたコードは、それが書かれている言語の規則に従う必要があります。つまり、UBが無害であると期待している場合でも、未定義の動作を呼び出さないようにする必要があります。

于 2012-12-08T23:10:57.410 に答える
4

あなたはおそらくあなたがコンピューティング&a - 1かそれに類似した何かをしていることを意味します。

(uintptr_t)&aポインタ比較が現在ほとんどのアーキテクチャで符号なし比較として実装されていて、それが現在のシステムの任意の境界よりも大きいことがわかっている場合でも、これを行わないでください。コンパイラー、最適化のために未定義の動作を利用します。彼らは今それを行っています、そして彼らが今それを利用しなければ、あなたが命令セットまたはプラットフォームから期待するかもしれない「保証」に関係なく、彼らは将来それを利用するでしょう。

詳細については、このよく知られた逸話を参照してください。

完全に異なるレジスタでは、1の補数や符号の大きさなど、さまざまなハードウェアの選択肢があったため、Cでは符号付きオーバーフローが未定義であると考えるかもしれません。したがって、プラットフォームが2の補数であることがわかっている場合、などの式(x+1) > xはを検出しMAX_INTます。

これは歴史的な理由かもしれませんが、その理由はもはや成り立ちません。符号付きオーバーフローは未定義であるため、式(x+1) > xxタイプは)は最新のコンパイラーによってint最適化されています。コンパイラの作成者は、未定義の元々の理由が利用可能なアーキテクチャの多様性であったことを気にしません。そして、ポインタを使って行っている未定義のことは、次のリストにあります。アーキテクチャが変更されたためではなく、コンパイラが最適化にますます積極的になっているために、未定義の動作を呼び出すと、プログラムは明日壊れます。1

于 2012-12-08T23:10:47.913 に答える
2

動的割り当てはで実行されheapます。(プログラムコード)とセクションの直後Heapのプロセスに存在します。http ://www.cprogramming.com/tutorial/virtual_memory_and_heaps.htmlを参照してください。したがって、ヒープ内の可能な最小アドレスは、これら3つのセグメントのサイズに依存します。したがって、特定のプログラムに依存するため、絶対的な答えはありません。address spacetextinitialized datauninitialized data

于 2012-12-08T23:17:07.850 に答える