構造体を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によって確保してない場合はいくら使用できたとしても、空いているとコンピュータでは認識されるため、何かヒープ領域を使う場合に勝手に上書きされてしまう可能性がある。

しかし、この考えでも、なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。

わかる方いましたらよろしくお願いします。

このQ&Aに関連する最新のQ&A

A 回答 (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/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 …
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

具体的な例を挙げてくださったおかげで、理解しやすかったです。ありがとうございます。
もちろんこのようなコードを多分に利用するとかそういったわけではないですが、気になったので質問させていただきました。
まだより深い、内部的な知識は全くないので、どういった実装になっているかなどしっかりと勉強していきたいと思います。
URLまで載せていただき感謝です。

お礼日時:2014/12/07 23:19

malloc じゃなくって, 単純に配列を使っても同じでしょ?

    • good
    • 0
この回答へのお礼

回答ありがとうございます。

確かに配列でも似たようなことが言えました。ただ、配列では要素数を越えた場合エラーが出てくれると思っているのですが、mallocにより確保したポインタではそのようなことが起こらなかったため疑問を持ってしまいました。

お礼日時:2014/12/07 23:26

C/C++ でのポインタについて、少し調べられた方が良いと思います。


ポインタ型は、配列として使えますが、全く別物です。
mallocは、指定のバイト数の領域を確保し、その先頭アドレスを返します。
(構造体 何個分のデータかどうかは、mallocの関与するところではない)
そのアドレスを構造体へのポインタとしてキャストする事で、構造体としての利用が可能となりますが、構造体何個分の領域が確保され、使えるかを管理するのは、完全にプログラマの責任で、セキュリティ上のバッファオーバーフロー問題とかに関係してくる事となります。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

現在大学の課題でプログラムを作っているときにふと生じた疑問でしたが、構造体へのポインタとしてのキャストをしていることによりそういったことが起こっていたんですね。
久しぶりにC言語を扱ったので、再度ポインタについて学び直したいと思います。

お礼日時:2014/12/07 23:23

>なぜ確保外の領域が構造体のサイズ分ずつ区切られているのか納得いきません。



区切られているワケではなく、構造体のサイズからコンパイラがアドレスを「算出」しているだけです。

>mallocによりヒープ領域から適当な空いているメモリのアドレスが渡されるため、そこからはヒープ領域より先に、限りがあるまで進めてしまうために確保外のサイズにアクセスしても使えてしまっている。

管理状態によります。
実際に読み書きする時に仮想アドレスにメモリを割り当てる。
とかの場合は、例外発生して死ぬ可能性もあります。
# OSが例外を受け取って、ライブラリに転送してごにょごにょ…とか、そういう場合もあるかも知れませんが。

いずれにしろ、正しい使い方ではないので何が起こっても文句は言えません。
# 確保された領域外の変数に値を設定したらハードディスクがフォーマットされてしまった。とかなっても。


バッファオーバーランを引き起こす正しいコードではありますけどね。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

Cの勉強はlinuxでやるため、VMwareの仮想環境上で行っているので、ハードが必要以上にフォーマットされることはとりあえず大丈夫だと思っています。

おっしゃるとおり、正しい使い方ではないのでもちろんこれを通すつもりではないですが、たまたま気になってしまって質問してしまいました。
当たり前ですが、実際ではmallocにより確保した分だけを使いたいと思います。

お礼日時:2014/12/07 23:11

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qゴキブリが出たので怖くてブラックキャップを設置したのですが、今日無事に確保しました。 餌の匂いで他の

ゴキブリが出たので怖くてブラックキャップを設置したのですが、今日無事に確保しました。

餌の匂いで他のゴキを引き寄せないように、ブラックキャップは処分した方が良いですか?

ブラックキャップがあるくらいで家の中に入ってきたりしないでしょうか?

Aベストアンサー

処分してはダメだよ。
ゴキブリは家の外にもたくさんいるので、そんな餌などなくても入って来るからね。
が、入ってきたゴキはブラックキャップを食べて死ぬ。
ブラックキャップがないと、「これ幸い」と子孫を増やす。
これでわかったかな?(笑)。

Q動的に作成した構造体配列の中に、さらに動的に構造体配列を作るには?

はじめまして。

この度、ちょっとした計算プログラムを作ることになったのですが、
タイトルにもありますように、
『動的に作成した構造体配列の中に、さらに動的に構造体配列を作る』
方法がわからずに困っています。
実際には下記のようにプログラムしたいのですが...

-------------------------------------------------
'a'の構造体の中に作られる'b'の配列数は、下記のように
'a'の配列の番号により違い、また'a'の配列数も最初の段階では未定です。

構造体'a'←配列数未定 構造体'b'←配列数未定
a[0]-----b[0]
 |    b[1]
 |    b[2]
 |
a[1]-----b[0]
 |    b[1]
 |
a[2]-----b[0]
 |    b[1]
 .    b[2]
 .    b[3]
 .

-------------------------------------------------
new演算子で'a'の配列は作れたのですが、その中の'b'の数の分だけ
配列を動的に作成する方法がわかりませんでした。

最初は'b'の配列を多めに取って計算すればよいと思っていましたが、
計算過程で'b'の配列数が10000を越えてしまう場合があり、
また'b'の構造体のサイズも大きめなので、断念せざるをえませんでした。

どなたか、このように配列を作成する方法を知っている方がいましたら、
是非教えていただきたいです。

下手な説明ですいません。

はじめまして。

この度、ちょっとした計算プログラムを作ることになったのですが、
タイトルにもありますように、
『動的に作成した構造体配列の中に、さらに動的に構造体配列を作る』
方法がわからずに困っています。
実際には下記のようにプログラムしたいのですが...

-------------------------------------------------
'a'の構造体の中に作られる'b'の配列数は、下記のように
'a'の配列の番号により違い、また'a'の配列数も最初の段階では未定です。

構造体'a'←配列数未定 構造体'b'←配列数...続きを読む

Aベストアンサー

struct typDataB{
 long lData1;
 long lData2;
};

struct typDataA{
 typDataB* uDataB;
};

void main()
{
 typDataA* uDataA;
 uDataA = new typDataA [10];
 uDataA[0].uDataB = new typDataB [20];
 uDataA[0].uDataB[2].lData1=0;
 uDataA[0].uDataB[2].lData2=2;
}
では、外しているかも

Qブラックキャップについて

ゴキブリ退治にブラックキャップという商品を購入しました。

ベランダに8個ほど設置したのですが、その半数は雨が降ると濡れる位置にあります。


ブラックキャップが雨に濡れてしまった場合、何か悪影響はありますか?

Aベストアンサー

あまりよくないと思います。内容物が溶けてしまうでしょうから。

でも、ゴキブリは隙間などに生息するので雨の当たる場所に置いてもあまり意味が無いとおもいます。
私も使っていますが、軒下やサンテラスの下等雨がかからず、物置場になっているような場所に接ししています。

Q構造体の動的確保について

ある変数により動的確保を行いたいのですが、構造体中の変数に対して動的確保はできるのでしょうか?

struct data{
int i[30]; /*←ここの配列を動的に確保したい*/
double d[40]; /*←ここの配列を動的に確保したい*/
}data1[10];

よろしくお願いします。

Aベストアンサー

> data構造体の方も動的に確保したいと考えております。
ならば data に対しても vector を使います。

#include <vector>

struct data {
std::vector<int> i;
std::vector<double> d;
data(int ni=10, int nd=10) : i(ni), d(nd) {}
};

int main() {
std::vector<data> data1(10); // data[0]..data1[9]
....
return 0;
}

Q対ゴキブリ兵器、ブラックキャップの次はなにがいいか

気温も暖かくなってきたので、そろそろ戦略的にヤツラへの兵器を決めようと思うのですが
去年の夏に設置したブラックキャップ(驚異的な成果を上げた)と同質のものだと
学習能力の高いヤツラには通用しないことが危惧されるので
次の兵器を何にしようか?と考えているのですが
一般的なホームセンターに売っているのでオススメのものを教えてください。
(ちなみに秋頃にはまたブラックキャップを設置する予定です)

Aベストアンサー

バルサン ゴキZero
http://www.lion.co.jp/ja/seihin/brand/068/08.htm
ゴキジェットプロ
http://www.earth-chem.co.jp/top01/gokiburi/gokijet/gokijet.html

ヤツラは最強すぎて嫌になっちゃいますね。
私は一般的な兵器しか使用しないんですが、
ここ数年は家でお会いしてませんので、今年も出ませんように・・・。

あと、ブラックキャップのような家型は中の毒餌がなくなると、
住みかにするケースもあるので回収も忘れずに・・・。

Qmallocで確保するメモリの領域を限定する方法

mallocで確保するメモリの領域を限定する方法というものは存在するのでしょうか?

例えば、
mallocを使ってメモリを確保するときに、
アドレス:0x00001000から0x00002000の間でメモリを確保してください。

といった感じです。
宜しくお願いいたします。

Aベストアンサー

特定アドレスのメモリを割り付けるのであれば、静的に割り付けるか、それに近い方法を取らざるをえません。
処理系に依存しない方法はありませんので、処理系を補足してください。

いずれにせよ、取りうる方法は限られています。
ひとつは、リンク時にアドレス指定で配列を割り付ける方法であり、もうひとつは(もし使えるのであれば)MMUを自分で制御して、該当アドレスに仮想メモリを配置する方法です。
ハードウェアの設計も自分でできる(能力的にも権限的にも)のであれば、もっと別の方法があるかもしれません。

Qゴキブリが出ました!ブラックキャップを置いてますが出ました!ゴキブリに会わなくて済むオススメアイ

ゴキブリが出ました!
ブラックキャップを置いてますが出ました!
ゴキブリに会わなくて済むオススメアイテムないですか?

Aベストアンサー

ブラックキャップの数が少ないのでは?
まさかひと箱程度で済ませてないですよね?
”ゴキブリがこないスプレー”を買いましょう。高いけど。

Q構造体を動的に確保&解放

度々お世話になってます。

構造体を動的に確保し、処理後メモリーリークが起こらないように解放したいです。
item を m_xcList.GetItemCount() 個、宣言したいです。

ご教授願いたいです。


▼ソースの一部抜粋▼

void CFileListCreatorDlg::SameItemCheck(CString mySwitch)
{

 LVITEM  lvi;
 int   index = 0;

 UpdateData();
 lvi.mask = LVIF_TEXT;

 CString FullPathString;
 CString myFileName;

 index = 0;
 while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){
  lvi.iItem = index;
  lvi.iSubItem = 0;   

  lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(_T("")));
  CFileListCreatorDlg::m_xcList.SetItem(&lvi);
  index++;
 }


 //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報
 //ファイル名、ファイル容量、修正日時により、重複チェック

 struct item
 {
  CString RepetitionNum; //ファイル重複識別ナンバー

  //int  Num;  //通し番号

  CString FullPath; //ファイルパス
  CString FileName; //ファイル名

  //CString ApproximateByte; //おおよそのデータサイズ//バイト

  CString AccurateByte;  //実際のデータサイズ//実バイト
  
  //TCHAR ModifyDate[20];  //修正日
  //CTime ModifyTime;  //修正時間
  
  CString ModifyTime;  //修正時間
  
  //TCHAR RemarksColumn[100];  //備考欄
 };


 //http://www-watt.mech.eng.osaka-u.ac.jp/~tasai/cp/lec1.html ← プログラム5を参考にしました。

 struct item *array;

 /* メモリの確保 */
 array = (struct item*)malloc(sizeof(struct item)*(CFileListCreatorDlg::m_xcList.GetItemCount()-1));
 if (array == NULL) {
  StatusStringSet(_T("memory allocation error\r\n"),0,TRUE);
  exit(EXIT_FAILURE);
 }

 //const int itemNum = sizeof item /sizeof array[0];

 int i;

 for (i = 0; i < CFileListCreatorDlg::m_xcList.GetItemCount(); i++) //初期化
 {
  array[i].RepetitionNum = _T(""); //ファイル重複識別ナンバー
  array[i].FileName = _T(""); //ファイル名
  array[i].AccurateByte = _T(""); //データサイズ
  array[i].ModifyTime = _T(""); //修正時間
 }

int cc;
 int dd;


 cc = 1;
 dd = 1;

 if(mySwitch == _T("SameItemCheck_BY_FileName")){
  //0:ファイル重複識別ナンバー 1:通し番号 2:フルパス 3:ファイル名 4:おおよそのデータサイズ 5:データサイズ 6:修正日 7:修正時間 8:備考欄 9:書式情報
  StatusStringSet(_T("ファイル名により、重複チェック"),0,FALSE);
  index = 0;

  while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){
   array[index].RepetitionNum = _T("");

   FullPathString = CFileListCreatorDlg::m_xcList.GetItemText(index,2);

   if(FullPathString != _T("")){
    array[index].FileName = FullPathToFileName(FullPathString);
   }

   for (dd = 0; dd <= index-1; dd++){
    if (array[dd].FileName == array[index].FileName){
     if (array[index].RepetitionNum != _T("")){
      array[dd].RepetitionNum = array[index].RepetitionNum;
      //" 重複番号欄に既に重複Noが、入っているとき"
     }else{
      //cc // " インクリメントcc"
       CString str;
       if (cc>=INT_MAX){
        str = _T("MAX-Value");
       }else{
        str.Format(_T("%d"),cc);
       }

       array[index].RepetitionNum = const_cast<LPTSTR>(static_cast<LPCTSTR>(str));
       if (array[dd].RepetitionNum != array[index].RepetitionNum){
        cc++;
       }

     }

     lvi.iItem = index;
     lvi.iSubItem = 0;   

     lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(array[index].RepetitionNum));
     CFileListCreatorDlg::m_xcList.SetItem(&lvi);
     UpdateData(FALSE);
     
     lvi.iItem = dd;
     lvi.iSubItem = 0;   

     lvi.pszText = const_cast<LPTSTR>(static_cast<LPCTSTR>(array[index].RepetitionNum));
     CFileListCreatorDlg::m_xcList.SetItem(&lvi);
     UpdateData(FALSE);
    }
   }
   index++;

   UpdateData(FALSE);
  }
 }else if(mySwitch == _T("SameItemCheck_By_DataSize")){
  //省略
 }
}
▲ソースの一部抜粋▲

コンパイルは通るのですが、実行時に↓のエラーがでます。
どこの部分ががおかしいのでしょうか??



 ▼エラーメッセージ▼

 FileListCreator.exe の 0x00f08ac1 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0xcdcdcdbd を読み込み中にアクセス違反が発生しました。

 void Empty() throw()
 {
  CStringData* pOldData = GetData();
  IAtlStringMgr* pStringMgr = pOldData->pStringMgr;
  if( pOldData->nDataLength == 0 )
  {
   return;
  }

  if( pOldData->IsLocked() )
  {
   // Don't reallocate a locked buffer that's shrinking
   SetLength( 0 );
  }
  else
  {
   pOldData->Release();
   CStringData* pNewData = pStringMgr->GetNilString();
   Attach( pNewData );
  }
 }

 ▲エラーメッセージ▲

汎用的なコードをお教え願いたいです。宜しくお願いします。

度々お世話になってます。

構造体を動的に確保し、処理後メモリーリークが起こらないように解放したいです。
item を m_xcList.GetItemCount() 個、宣言したいです。

ご教授願いたいです。


▼ソースの一部抜粋▼

void CFileListCreatorDlg::SameItemCheck(CString mySwitch)
{

 LVITEM  lvi;
 int   index = 0;

 UpdateData();
 lvi.mask = LVIF_TEXT;

 CString FullPathString;
 CString myFileName;

 index = 0;
 while (index < CFileListCreatorDlg::m_xcList.GetItemCount()){
  lvi....続きを読む

Aベストアンサー

#include <stdio.h>

int main()
{
int a[5];
for (i=1; i<=5; ++i)
a[i] = i*i;
for (i=1; i<=5; ++i)
printf("a[%d]=%d\n", i, a[i]);
return 0;
}

というプログラムは間違っています. どこが間違いかわかりますか?

Qブラックキャップ 効果がない

ブラックキャップを6畳の部屋に10個くらい置いてるのですが
それでも今年2匹ゴキブリが出ました。

築10年で4月に引っ越してきて、4月に設置しました。

出過ぎじゃないですか?
私の部屋が異常なのでしょうか?

食品は全て冷蔵庫にしまっているつもりです。

Aベストアンサー

そりゃ部屋の中にたくさんエサを置いておけば食べるために部屋に入ってくるでしょうよ。
ブラックキャップってゴキブリを寄せ付けないアイテムではなく、引き寄せて食べさせるための毒エサですよ?
設置場所を考え直すことを勧めます。

あと、半年くらいで誘引成分が抜けて効果がなくなるので、秋頃には新たに置きなおしましょう。

Q構造体へのポインタの動的確保について

構造体へのポインタを動的確保しようとmalloc関数を使用すると
segmentation faultが起きます。

typedef struct cell{
char *word;
int count;
struct cell *next;
}node_t;

という構造体で

node_t *ptr=(node_t*)malloc(sizeof(node_t)*num);

という風に動的確保しようとするとsegmentation faultが起きました。

gdbを使って調べると

Starting program: /home/programII/week05/a.out file1 file2

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b4ce36 in ?? () from /lib/x86_64-linux-gnu/libc.so.6

というメッセージが返ってきます。

これはライブラリとのリンクが正しく行われていないということでしょうか?

しかし、ポインタの動的確保以外でmalloc関数を使用すると
正常に動作するのでライブラリ自体が無いわけではないようです。

ptr[2]といった風にポインタを参照したいのですが上手くいきません。

よろしくお願いします。

構造体へのポインタを動的確保しようとmalloc関数を使用すると
segmentation faultが起きます。

typedef struct cell{
char *word;
int count;
struct cell *next;
}node_t;

という構造体で

node_t *ptr=(node_t*)malloc(sizeof(node_t)*num);

という風に動的確保しようとするとsegmentation faultが起きました。

gdbを使って調べると

Starting program: /home/programII/week05/a.out file1 file2

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b4ce36 in ?? () from /lib/x86...続きを読む

Aベストアンサー

まぁ、もろもろ指摘が既に入っていますが……。

nodePrepend()にブレークポイント張って、変数の「中身」を確認しながらステップ実行して下さい。
たぶん、forループが1回まわる前に気づくでしょう。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング