web-dev-qa-db-ja.com

malloc(0)のポイントは何ですか?

これを見ただけ code:

artist = (char *) malloc(0);

そして、なぜこれを行うのだろうと思っていましたか?

114
jldupont

仕様によると、 malloc(0) は、「nullポインターまたはfree()に正常に渡すことができる一意のポインター」を返します。

これにより基本的に何も割り当てられませんが、心配せずに「アーティスト」変数をfree()の呼び出しに渡します。実用的な目的では、次のこととほとんど同じです。

artist = NULL;
117
Reed Copsey

C規格(C17 7.22.3/1)は次のように述べています:

要求されたスペースのサイズがゼロの場合、動作は実装定義です:nullポインターが返されるか、または動作はサイズがゼロ以外の値であるかのようになりますが、返されたポインターはオブジェクトへのアクセスに使用されません。

したがって、malloc(0)NULLまたは有効なポインター逆参照されない場合がありますを返します。どちらの場合でも、free()を呼び出すことは完全に有効です。

malloc(0)がたとえばループで呼び出され、nがゼロの場合を除いて、malloc(n)の使用はあまりないと思います。

リンクのコードを見ると、著者には2つの誤解があったと思います。

  • malloc(0)は有効なポインターを返しますalways
  • free(0)は悪いです。

そのため、彼はartistおよび他の変数に常に「有効な」値があることを確認しました。コメントには次のように書かれています:// these must always point at malloc'd data

49
Alok Singhal

malloc(0)の動作は実装固有です。ライブラリは、メモリを割り当てずに、NULLを返すか、通常のmalloc動作を行うことができます。それが何であれ、それはどこかに文書化されなければなりません。

通常、有効で一意のポインターを返しますが、逆参照しないでください。また、実際には何も割り当てなかったにもかかわらず、メモリを消費する可能性があることに注意してください。

Null以外のmalloc(0)ポインターを再割り当てすることは可能です。

ただし、malloc(0)をそのまま使用することはあまり役に立ちません。これは主に、動的割り当てがゼロバイトであり、それを検証する必要がない場合に使用されます。

10
Coincoin

このページの別の場所に「malloc(0)は有効なメモリアドレスを返し、その範囲はメモリを割り当てられているポインタのタイプに依存します」という回答があります。この声明は間違っています(その答えに直接コメントするほどの評判がないので、このコメントをその下に直接置くことはできません)。

Malloc(0)を実行するとnotが正しいサイズのメモリを自動的に割り当てます。 malloc関数は、結果のキャスト先を認識しません。 malloc関数は、引数として指定したサイズ番号のみに依存します。 0ではなくintを保持するのに十分なストレージを取得するには、malloc(sizeof(int))を実行する必要があります。

5
Krellan

malloc(0)は、コードが実装に固有の動作に依存していない限り、意味がありません。コードが移植可能であることを意図している場合、malloc(0)からのNULL戻りが失敗ではないという事実を考慮する必要があります。とにかくartistにNULLを単に割り当てないのはなぜですか、それは有効な成功結果であり、コードが少なく、メンテナンスプログラマがそれを理解するのに時間をかけないからです。

malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)またはmalloc(some_variable_which_might_be_zero)を使用することもできますが、値が0の場合にNULL戻り値を失敗として扱わないように特別な注意を払う必要がありますが、サイズ0が想定されます大丈夫。

3
Steve Jessop

この辺りには半分の正解がたくさんあるので、ここに難しい事実があります。 malloc()のマンページには次のように書かれています:

サイズが0の場合、malloc()はNULL、またはfree()に後で正常に渡すことができる一意のポインター値のいずれかを返します。

つまり、malloc(0)の結果が一意であるかNULLでないという保証はまったくありません。唯一の保証は、free()の定義によって提供されます。ここでも、マンページの内容は次のとおりです。

PtrがNULLの場合、操作は実行されません。

したがって、malloc(0)が返すものは何でも、free()に安全に渡すことができます。しかし、NULLポインターも同様です。

その結果、書き込みartist = malloc(0);書き込みよりも優れているartist = NULL;

3
cmaster

確かに、私はこれをこれまで見たことがありません。これは、この構文を見たのは初めてです。つまり、機能過剰の古典的なケースです。リードの答えに関連して、オーバーロードされた関数reallocのように見える類似したものがあることを指摘したいと思います。

  • fooはNULLでなく、サイズはゼロ、realloc(foo, size);です。 NULL以外のポインターとサイズ0をreallocに渡すと、reallocはfree(…)を呼び出したかのように動作します
  • fooはNULLで、サイズは0以外で1より大きいrealloc(foo, size);。 NULLポインターを渡し、サイズがゼロ以外の場合、reallocはmalloc(…)を呼び出したかのように動作します

これがお役に立てば幸いです、よろしく、トム。

2
t0mm13b

なぜこれをしてはいけないのか...

Mallocの戻り値は実装に依存するため、NULLポインターまたは他のアドレスが返される場合があります。エラー処理コードがサイズと戻り値の両方をチェックしない場合、これによりヒープバッファオーバーフローが発生する可能性があり、安定性の問題(クラッシュ)またはさらに深刻なセキュリティの問題につながります。

サイズがゼロで実装がNULL以外の値を返す場合、返されたアドレスを介してメモリにさらにアクセスするとヒープが破損するこの例を考えてください。

size_t size;

/* Initialize size, possibly by user-controlled input */

int *list = (int *)malloc(size);
if (list == NULL) {
  /* Handle allocation error */
}
else {
  /* Continue processing list */
}

このSecure Codingページ を参照してください。CERTCoding Standardsでは、上記の例を取り上げてさらに読みました。

2
auselen

行われた質問に実際に答えるために:それをする理由はありません

1
Paolo

Windowsの場合:

  • void *p = malloc(0);は、ローカルヒープに長さゼロのバッファを割り当てます。返されるポインターは有効なヒープポインターです。
  • mallocは最終的にHeapAllocを呼び出すデフォルトのCランタイムヒープを使用してRtlAllocateHeapを呼び出します。
  • free(p);は、HeapFreeを使用して、ヒープ上の長さ0のバッファーを解放します。解放しないと、メモリリークが発生します。
0
sam msft

malloc(0)はNULLまたは有効なポインタを返しますが、これらはfreeに正しく渡すことができます。そして、それが指し示すメモリは役に立たないか、読み書きできないように見えますが、常にそうであるとは限りません。 :)

int *i = malloc(0);
*i = 100;
printf("%d", *i);

ここではセグメンテーション違反が予想されますが、驚くことに、これは100を出力します!これは、mallocを初めて呼び出すときに、mallocが実際に大量のメモリを要求するためです。その後のmallocの呼び出しはすべて、その大きなチャンクのメモリを使用します。その巨大なチャンクが終わった後にのみ、新しいメモリが要求されます。

Malloc(0)の使用:後続のmalloc呼び出しをより高速にしたい場合は、malloc(0)を呼び出してください(Edgeの場合を除く)。

0
Sagar Bhosale

実際には非常に便利であり、(明らかに私見では)、NULLポインターを返すという許可された動作は壊れています。動的ポインターは、それが指すものだけでなく、アドレスが一意であるという事実にも役立ちます。 NULLを返すと、その2番目のプロパティが削除されます。私がプログラムするすべての組み込みmalloc(実際には非常に頻繁に)には、この動作があります。

0
Scott Franco