質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

1061閲覧

c言語 malloc で確保したアドレスの差が常に20の理由とは

akiyama3284pga

総合スコア186

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2022/03/31 03:45

編集2022/03/31 04:00

自分のwindows10 64bit環境でmallocしてその返り値を確認したところ、

int* aaa = (int*)malloc(sizeof(int)); int* bbb = (int*)malloc(sizeof(int)); printf("aaa:%p \n", aaa); // out: aaa:0x7fffb83392a0 printf("bbb:%p \n", bbb); // out: bbb:0x7fffb83392c0 (差20)

のように常に20byte(訂正: 32byte)の刻みとなっております。
素人目線ではintで確保したのだから8byte間隔になるのが普通なのではないかと考えてしまいます。

ちなみにcharでも、unsigned long long intでも同じ20間隔となりました。

バラバラのヒープ領域に確保されるという仕様であれば仕方ないかとも考えましたが、
ポインタの配列を使用した際にも、20の差で確保されております。
配列はアドレスが隣り合った連続ではいけないと思いますのでこれではまずいのではないでしょうか...

int* arry[3]; for (int i=0; i<3; i++){ arry[i] = (int*)malloc(sizeof(int)); *arry[i] = i; /* 下はそれぞれ要素間が20 */ printf("*arr[i]p: %p\n", *(arry + i); }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

素人目線ではintで確保したのだから8byte間隔になるのが普通なのではないかと考えてしまいます。

でもそうはならない。

malloc(N) で確保したNバイト領域は連続していることが保証されます(なので malloc(N*sizeof(int)) で得られた領域は int[N] として使える)が、

malloc(M), malloc(N) を立て続けにやって M+Nバイトが連続する保証はどこにもありません。

[追記] やりたいことはコレ↓か?

C

1#include <stdio.h> 2#include <stdlib.h> 3 4int main() { 5 int** arry = malloc(3*sizeof(int*)); // int* を 3つ、連続して確保 6 for (int i=0; i<3; i++){ 7 arry[i] = (int*)malloc(sizeof(int)); 8 *arry[i] = i; 9 printf("*arr[%d] = %d at %p\n", i, *arry[i], arry+i); 10 } 11 return 0; 12}

投稿2022/03/31 04:31

編集2022/03/31 05:14
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akiyama3284pga

2022/03/31 05:42

ありがとうございます。 的確なご回答感謝いたします。 自分は知るべき対象へのアクセス方法を誤っていたようです。 まさに追記の点が知りたかったものでございます。 ・malloc(N*sizeof(int)) で得られた領域は int[N] として使える)が、 malloc(M), malloc(N) を立て続けにやって M+Nバイトが連続する保証はどこにもない。 ※今回ではたまたま連続したが、 int* aaa = (int*)malloc(sizeof(int)); int* bbb = (int*)malloc(sizeof(int)); でヒープ上の確保した領域が連続する可能性は100%ではなく保障外 という点を忘れないよう焼き付けておきます。<(_ _)>
guest

0

ベストアンサー

mallocを2回読んで連続していないことに関してはそもそもそれが保証されていないという話もありますし、
mallocでメモリを確保するとき、malloc/freeのシステムが使用するための領域も一緒に確保しているというのもあります。

参考 :mallocの動作を追いかける(mmap編) - Qiita

配列の方のコードについては、
連続しているのはarry[0],arry[1],arry[2]アドレスなので
見るべきは
printf("*arr[i]p: %p\n", (arry + i);です

投稿2022/03/31 04:12

編集2022/03/31 05:02
ozwk

総合スコア13528

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akiyama3284pga

2022/03/31 05:38

的確なご回答ありがとうございます。 知るべき対象へのアクセス方法を誤っていたようです。汗 おっしゃる通り、 printf("*arr[i]p: %p\n", (arry + i); で出力されるものが知りたかったものであり、連続性とサイズを確認いたしました。 ・配列のアドレスは連続している必要があるが、その先の確保したヒープ領域の連続性は必要ないと腑に落ち ・mallocを2回読んで連続していないことに関してはそもそもそれが保証されていない という点と、 ・システムが使用するための領域も必要だから実際に確保されるサイズは指定分+α これらの点をしっかり忘れないようしておきたいと存じます。
guest

0

20h(32byte)の差の誤りですよね?

VSならランタイムのソースコードはありましたかねぇ。
メモリ管理で必要な情報が間に挟まっているかと思われます。
なので、確保した領域外を破壊するとmalloc()やらfree()やらでアクセス違反になることがある。と。

投稿2022/03/31 03:50

setoppu

総合スコア292

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akiyama3284pga

2022/03/31 05:43

ありがとうございます。<(_ _)> 無事理解するに至りました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問