- ベストアンサー
mallocによる確保外の領域への参照
- mallocを使用して確保した領域外にアクセスできる理由について疑問があります。
- mallocによりヒープ領域から適当なアドレスが渡されるため、それ以上のアドレスにもアクセスできる可能性があります。
- このような場合、確保外の領域にアクセスすることは予測不可能な結果を引き起こす可能性があるため、注意が必要です。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
> しかし、この考えでも、なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。 #1の回答にに補足します。 int x[10]; とあったとき、x + 3と(char*)(x) + 3は同じ値でしょうか違う値でしょうか? *(x + 3)とあったら、コンパイラーはxはint型の配列だからということで、xが100だったとして、x + 3は100 + sizeof(int) * 3の値になります。(char*)(x) + 3は100 + sizeof(char)*3の値になります。 確保しているわけではなく、コンパイラーがそう扱うというだけです。確保されているかどうかをコンパイラーは気にしませんし、実行してみるまでそれはわかりません。(配列として確保している場合、コンパイラーによっては警告くらい出しそうですが。) 「何かヒープ領域を使う場合に勝手に上書きされてしまう可能性がある」どころか、ライブラリーが管理のために作っている構造を破壊して、予測不能な動きをさせることもありそうですが。 mallocの動きはmallocの実装によって異なります。 様々なmallocの実装の解説はすでに多数公開されていますからそれらを読んでみてはいかがでしょうか。 http://ja.wikipedia.org/wiki/Malloc glibc http://www.slideshare.net/kosaki55tea/glibc-malloc http://www.valinux.co.jp/technologylibrary/document/linux/malloc0001/ ソースコード: https://sourceware.org/git/?p=glibc.git;a=tree;f=malloc;h=da19ef618bb9565ea526243de099f2a18a76cbe6;hb=HEAD tcmalloc http://goog-perftools.sourceforge.net/doc/tcmalloc.html ソースコード: https://code.google.com/p/gperftools/source/browse/#git%2Fsrc%2Fgperftools jemalloc https://www.facebook.com/note.php?note_id=480222803919 和訳: http://d.hatena.ne.jp/repeatedly/20110110/1294634486 ソースコード: http://fxr.watson.org/fxr/source/stdlib/malloc.c?v=FREEBSD-LIBC
その他の回答 (3)
- Tacosan
- ベストアンサー率23% (3656/15482)
malloc じゃなくって, 単純に配列を使っても同じでしょ?
お礼
回答ありがとうございます。 確かに配列でも似たようなことが言えました。ただ、配列では要素数を越えた場合エラーが出てくれると思っているのですが、mallocにより確保したポインタではそのようなことが起こらなかったため疑問を持ってしまいました。
C/C++ でのポインタについて、少し調べられた方が良いと思います。 ポインタ型は、配列として使えますが、全く別物です。 mallocは、指定のバイト数の領域を確保し、その先頭アドレスを返します。 (構造体 何個分のデータかどうかは、mallocの関与するところではない) そのアドレスを構造体へのポインタとしてキャストする事で、構造体としての利用が可能となりますが、構造体何個分の領域が確保され、使えるかを管理するのは、完全にプログラマの責任で、セキュリティ上のバッファオーバーフロー問題とかに関係してくる事となります。
お礼
回答ありがとうございます。 現在大学の課題でプログラムを作っているときにふと生じた疑問でしたが、構造体へのポインタとしてのキャストをしていることによりそういったことが起こっていたんですね。 久しぶりにC言語を扱ったので、再度ポインタについて学び直したいと思います。
- Wr5
- ベストアンサー率53% (2173/4061)
>なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。 区切られているワケではなく、構造体のサイズからコンパイラがアドレスを「算出」しているだけです。 >mallocによりヒープ領域から適当な空いているメモリのアドレスが渡されるため、そこからはヒープ領域より先に、限りがあるまで進めてしまうために確保外のサイズにアクセスしても使えてしまっている。 管理状態によります。 実際に読み書きする時に仮想アドレスにメモリを割り当てる。 とかの場合は、例外発生して死ぬ可能性もあります。 # OSが例外を受け取って、ライブラリに転送してごにょごにょ…とか、そういう場合もあるかも知れませんが。 いずれにしろ、正しい使い方ではないので何が起こっても文句は言えません。 # 確保された領域外の変数に値を設定したらハードディスクがフォーマットされてしまった。とかなっても。 バッファオーバーランを引き起こす正しいコードではありますけどね。
お礼
回答ありがとうございます。 Cの勉強はlinuxでやるため、VMwareの仮想環境上で行っているので、ハードが必要以上にフォーマットされることはとりあえず大丈夫だと思っています。 おっしゃるとおり、正しい使い方ではないのでもちろんこれを通すつもりではないですが、たまたま気になってしまって質問してしまいました。 当たり前ですが、実際ではmallocにより確保した分だけを使いたいと思います。
お礼
回答ありがとうございます。 具体的な例を挙げてくださったおかげで、理解しやすかったです。ありがとうございます。 もちろんこのようなコードを多分に利用するとかそういったわけではないですが、気になったので質問させていただきました。 まだより深い、内部的な知識は全くないので、どういった実装になっているかなどしっかりと勉強していきたいと思います。 URLまで載せていただき感謝です。