
構造体をmallocにより動的確保を行っていたのですが、例えば
typedef struct _point{
int x, y;
} point;
point *pelem_point;
pelem_point = (point *)malloc(sizeof(point)*5);
このように、point型の構造体を5つ確保するとします。
しかし、
(pelem_point+100)->x = 1;
(pelem_point+100)->y = 2;
printf("%d\n", (pelem_point+100)->x);
printf("%d\n", (pelem_point+100)->y);
とやったら、確保していない100個先のところも構造体として利用できました。
なぜなのでしょうか。
自分の考えではこのようになりました。
mallocによりヒープ領域から適当な空いているメモリのアドレスが渡されるため、そこからはヒープ領域より先に、限りがあるまで進めてしまうために確保外のサイズにアクセスしても使えてしまっている。
また、mallocにより確保した場合は使用中のラベルがはられるため他に侵されることはないが、先の例のようにmallocによって確保してない場合はいくら使用できたとしても、空いているとコンピュータでは認識されるため、何かヒープ領域を使う場合に勝手に上書きされてしまう可能性がある。
しかし、この考えでも、なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。
わかる方いましたらよろしくお願いします。
No.2ベストアンサー
- 回答日時:
> しかし、この考えでも、なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。
#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/docum …
ソースコード: https://sourceware.org/git/?p=glibc.git;a=tree;f …
tcmalloc
http://goog-perftools.sourceforge.net/doc/tcmall …
ソースコード: https://code.google.com/p/gperftools/source/brow …
jemalloc
https://www.facebook.com/note.php?note_id=480222 …
和訳: http://d.hatena.ne.jp/repeatedly/20110110/129463 …
ソースコード: http://fxr.watson.org/fxr/source/stdlib/malloc.c …
回答ありがとうございます。
具体的な例を挙げてくださったおかげで、理解しやすかったです。ありがとうございます。
もちろんこのようなコードを多分に利用するとかそういったわけではないですが、気になったので質問させていただきました。
まだより深い、内部的な知識は全くないので、どういった実装になっているかなどしっかりと勉強していきたいと思います。
URLまで載せていただき感謝です。
No.4
- 回答日時:
malloc じゃなくって, 単純に配列を使っても同じでしょ?
回答ありがとうございます。
確かに配列でも似たようなことが言えました。ただ、配列では要素数を越えた場合エラーが出てくれると思っているのですが、mallocにより確保したポインタではそのようなことが起こらなかったため疑問を持ってしまいました。
No.3
- 回答日時:
C/C++ でのポインタについて、少し調べられた方が良いと思います。
ポインタ型は、配列として使えますが、全く別物です。
mallocは、指定のバイト数の領域を確保し、その先頭アドレスを返します。
(構造体 何個分のデータかどうかは、mallocの関与するところではない)
そのアドレスを構造体へのポインタとしてキャストする事で、構造体としての利用が可能となりますが、構造体何個分の領域が確保され、使えるかを管理するのは、完全にプログラマの責任で、セキュリティ上のバッファオーバーフロー問題とかに関係してくる事となります。
回答ありがとうございます。
現在大学の課題でプログラムを作っているときにふと生じた疑問でしたが、構造体へのポインタとしてのキャストをしていることによりそういったことが起こっていたんですね。
久しぶりにC言語を扱ったので、再度ポインタについて学び直したいと思います。
No.1
- 回答日時:
>なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。
区切られているワケではなく、構造体のサイズからコンパイラがアドレスを「算出」しているだけです。
>mallocによりヒープ領域から適当な空いているメモリのアドレスが渡されるため、そこからはヒープ領域より先に、限りがあるまで進めてしまうために確保外のサイズにアクセスしても使えてしまっている。
管理状態によります。
実際に読み書きする時に仮想アドレスにメモリを割り当てる。
とかの場合は、例外発生して死ぬ可能性もあります。
# OSが例外を受け取って、ライブラリに転送してごにょごにょ…とか、そういう場合もあるかも知れませんが。
いずれにしろ、正しい使い方ではないので何が起こっても文句は言えません。
# 確保された領域外の変数に値を設定したらハードディスクがフォーマットされてしまった。とかなっても。
バッファオーバーランを引き起こす正しいコードではありますけどね。
回答ありがとうございます。
Cの勉強はlinuxでやるため、VMwareの仮想環境上で行っているので、ハードが必要以上にフォーマットされることはとりあえず大丈夫だと思っています。
おっしゃるとおり、正しい使い方ではないのでもちろんこれを通すつもりではないですが、たまたま気になってしまって質問してしまいました。
当たり前ですが、実際ではmallocにより確保した分だけを使いたいと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- ポイントサービス・マイル マイナンバーPOINTについて 1 2022/12/24 08:20
- ポイントサービス・マイル docomoポイントについてです。 今まで9000pointあったのが いきなり120pointにな 6 2022/07/01 10:59
- C言語・C++・C# 未解決の外部シンボル _printfが関数_mainで参照されました 1 2022/09/18 15:28
- スーパー・コンビニ イオンカードで、レジでWAON POINTを使って支払いたい時、電子マネーWAONカードのように機械 1 2023/03/12 05:44
- Excel(エクセル) RANK.EQとCOUNTIFSの組み合わせで同ポイントの場合、違う条件を加えて順位を付けたい。 1 2022/08/30 19:49
- 英語 "by a ~ 0.5 percentage point"が単数となる理由等について 2 2023/05/11 10:41
- Java java 引数 戻り値のあるメソッド 3 2023/02/12 06:23
- 楽天市場 楽天モバイル 楽天期間限定ポイント 使用はJCBギフトカード ガソリンはどうでしょうか 2 2022/06/29 01:06
- 英語 この英文の An important point is the degree of exposure 1 2022/08/03 19:54
- ポイントサービス・マイル WAON POINTと、WAONポイントは、違うのですか。 2 2023/07/07 20:50
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
allocってなんですか?
-
c言語のポインタへの文字列入力...
-
メモリ不足になってしまう。
-
ビットをローテートするプログ...
-
mallocで確保するメモリの領域...
-
CreateFileMapping について
-
C++で、メンバもヒープに確保さ...
-
sprintf の使い方について
-
UNIX socket TCP 受信バッファ...
-
プログラムが途中で強制終了し...
-
free関数で動作が止まる
-
ヒープメモリの解放について
-
c言語のメモリの確保について
-
MFCのCStringについて
-
メモリをたくさん使うテストプ...
-
構造体でchar name[]と*nameの...
-
newしないオブジェクトについて
-
関数から配列を返すには?
-
ExcelVBAでのkernel32(64bit)
-
セグメントエラー
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語のポインタへの文字列入力...
-
allocってなんですか?
-
newしないオブジェクトについて
-
malloc呼び出し時のセグメンテ...
-
入れ子になった構造体について
-
ヒープメモリの解放について
-
ビットをローテートするプログ...
-
C++で、メンバもヒープに確保さ...
-
void*型のデータサイズ
-
Win32APIでのメモリ管理について
-
配列の添え字の最大数とは?
-
C++のnewで確保したメモリーの...
-
プログラムが途中で強制終了し...
-
C言語 mallocとfreeについて
-
win32APIのHeapAlloc()の使い方...
-
LoadLibraryでAccess Violation...
-
グローバル変数のサイズ
-
MFCのCStringについて
-
メモリ不足になってしまう。
-
ヒープの実際の限界値は?
おすすめ情報