回答:
仕様によると、malloc(0)は「nullポインターまたはfree()に正常に渡すことができる一意のポインター」を返します。
これは基本的に何も割り当てませんが、心配することなくfree()の呼び出しに「artist」変数を渡します。実用上は、次のようにするのとほとんど同じです。
artist = NULL;
C標準(C17 7.22.3 / 1)は言う:
要求されたスペースのサイズがゼロの場合、動作は実装定義です。ヌルポインターが返されるか、返されたポインターがオブジェクトへのアクセスに使用されないことを除いて、サイズがゼロ以外の値であるかのように動作します。
そのため、を参照したり、逆参照できない有効なポインタをmalloc(0)
返すことができます。どちらの場合でも、それを呼び出すことは完全に有効です。NULL
free()
例えばループで呼び出されたmalloc(0)
場合を除いて、私は本当にあまり役に立たないと思いますmalloc(n)
、そしてn
ゼロのます。
リンクのコードを見ると、著者には2つの誤解があると思います。
malloc(0)
有効なポインタを返し、常に、およびfree(0)
悪い。したがって、彼はartist
、他の変数が常に「有効な」値を持っていることを確認しました。コメントは多くを言います:// these must always point at malloc'd data
。
malloc(0)
、有効なポインタを返され、その後、malloc()
戻ってNULL
常に手段「失敗」を、そして0
より一貫性のある、もはや特別なケースではありません。
malloc
メモリの取得に失敗する状況は実装によって定義されるため、実装では、サイズ0の割り当てが常に満たされない(ENOMEM
)と定義でき、malloc(0)
0を返す(とのerrno==ENOMEM
)は一貫しています。:-)
realloc
はポインタを返すことができますmalloc(0)
か?できますrealloc((char*)NULL)
か?
malloc(0)の動作は実装固有です。ライブラリはNULLを返すか、メモリが割り当てられていない通常のmalloc動作を行うことができます。それが何であれ、それはどこかに文書化されなければなりません。
通常、有効で一意であるが逆参照されるべきでないポインタを返します。また、実際には何も割り当てなかった場合でも、メモリを消費する可能性があることに注意してください。
null以外のmalloc(0)ポインタを再割り当てすることができます。
ただし、malloc(0)を逐語的に使用してもあまり役に立ちません。これは主に、動的割り当てが0バイトで、検証する必要がない場合に使用されます。
malloc()
「ハウスキーピング情報」をどこかに保持する必要があります(たとえば、この割り当てられたブロックのサイズ、およびその他の補助データ)。したがって、malloc(0)
が返されない場合はNULL
、メモリを使用してその情報を格納し、free()
dでない場合はメモリリークを構成します。
malloc()
ユーザーが返さない一意のポインタを返すか、を返すことができますNULL
。
malloc(0)
。ただし、標準Cライブラリのまったく同じ実装では、NULLをrealloc(ptr, 0)
解放ptr
して返します。
このページの別の場所に「malloc(0)は有効なメモリアドレスを返し、その範囲はメモリが割り当てられているポインタのタイプによって異なる」という回答があります。このステートメントは正しくありません(その回答に直接コメントするのに十分な評判がないため、このコメントをそのすぐ下に置くことはできません)。
malloc(0)を実行しても、正しいサイズのメモリが自動的に割り当てられません。malloc関数は、結果のキャスト先を認識していません。malloc関数は、引数として指定したサイズ番号に完全に依存しています。malloc(sizeof(int))を実行して、たとえば0ではなくintを保持するのに十分なストレージを取得する必要があります。
malloc(0)
コードが実装に固有の動作に依存していない限り、私には意味がありません。コードが移植可能であることを意図している場合、NULLからの戻り値malloc(0)
は失敗ではないという事実を考慮する必要があります。それで、artist
とにかくNULLを割り当てないでください。それは有効な成功結果であり、コードが少なく、メンテナンスプログラマが時間をかけてそれを理解する必要がないためです。
malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO)
または、malloc(some_variable_which_might_be_zero)
おそらくそれらの用途があるかもしれませんが、値が0の場合、NULLの戻りを失敗として扱わないように特別な注意を払う必要がありますが、サイズは0でも問題ありません。
この辺りには真実の答えがたくさんあるので、ここに難しい事実があります。のマンページはmalloc()
言う:
sizeが0の場合、malloc()はNULL、または後でfree()に正常に渡すことができる一意のポインタ値を返します。
つまり、の結果がmalloc(0)
一意であるか、またはNULL ではないという保証はまったくありません。唯一の保証はの定義によって提供されfree()
ます。ここでも、マンページに次のように記載されています。
ptrがNULLの場合、操作は実行されません。
したがって、malloc(0)
戻り値が何であれ、安全にに渡すことができますfree()
。しかし、NULL
ポインタも同様です。
したがって、書くこと は書くことよりも決して良いことでartist = malloc(0);
はありません artist = NULL;
malloc(0)
すれば、たとえば0x1を返すfree()
ことができ、0x0の場合と同じように0x1の特別なケースのチェックを行うことができます。
NULL
、または一意のポインタ」でなければならないことが指定されていません。代わりに、「nullポインターまたは割り当てられた領域へのポインターのいずれか」。一意の要件はありません。一意ではない特別な値を返すOTOHは、一意の値に依存するコードを混乱させる可能性があります。おそらくSOのコーナーケースの質問
man
* nixで使用される実装定義のフォームを文書化することもできます。この場合はそうではありませんが、それでも一般的なCの標準的なソースではありません
なぜこれをしてはいけないのか...
mallocの戻り値は実装に依存しているため、NULLポインターまたはその他のアドレスが返される場合があります。エラー処理コードがサイズと戻り値の両方をチェックしない場合、これによりヒープバッファオーバーフローが発生し、安定性の問題(クラッシュ)またはセキュリティの問題がさらに悪化する可能性があります。
この例を考えてみましょう。返されたアドレスを介してメモリにさらにアクセスすると、ヒープiffのサイズが破損し、実装は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 */
}
詳細については、上記の例を取り上げたCERT Coding StandardsのこのSecure Codingページを参照してください。
確かに、私はこれまでこれまで見たことがありません。これは、この構文を見たのは初めてです。リードの回答に関連して、オーバーロードされた関数のように見える同様のものが存在することを指摘したいと思いますrealloc
。
realloc(foo, size);
。NULL以外のポインタとサイズ0をreallocに渡すと、reallocはfree(…)を呼び出した場合と同様に動作します。realloc(foo, size);
。NULLポインターを渡し、サイズがゼロ以外の場合、reallocは、malloc(…)を呼び出した場合と同様に動作します。よろしくお願いいたします。トム。
malloc(0)は、NULLまたは空に正しく渡すことができる有効なポインタを返します。そして、それが指すメモリは役に立たないか、読み書きできないように見えますが、常にそうであるとは限りません。:)
int *i = malloc(0);
*i = 100;
printf("%d", *i);
ここではセグメンテーション違反が予想されますが、驚いたことに、これは100を出力します これは、mallocを初めて呼び出すときに、mallocが実際に大量のメモリを要求するためです。その後、mallocを呼び出すたびに、その大きなチャンクのメモリが使用されます。その巨大なチャンクが終わって初めて、新しいメモリが要求されます。
malloc(0)の使用:後続のmalloc呼び出しをより高速にしたい場合は、malloc(0)を呼び出すとそれが実行されます(エッジの場合を除く)。
*i
あなたの場合、への書き込みはクラッシュしないかもしれませんが、それでも未定義の動作です。鼻の悪魔に気をつけろ!
malloc(0)
。NULL以外の値を返すこれらの実装では、特にDEBUGビルドでは、要求よりも多くの割り当てが行われ、内部ヘッダーの直後を指すポインターが表示されます。これは、あなたが取得することができます感じあなたが割り当て一連の前と後にこれを取得する場合、実際のメモリ使用量のために。例:void* before = malloc(0); ... void* after = malloc(0); long long total = after - before;
またはそのようなもの。
malloc(0)
。どの章もあなたが参照しているのか言ってもらえますか?正確な引用を提供することもいいでしょう。
わかりません。私が見つけたいくつかのランダムなmallocソースコードによると、0を入力すると戻り値がNULLになります。したがって、アーティストポインタをNULLに設定するのはおかしな方法です。
http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html
これは、valgrindメモリチェックツールで実行した後の分析です。
==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740== in use at exit: 0 bytes in 0 blocks
==16740== total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible
そしてこれが私のサンプルコードです:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
//int i;
char *p1;
p1 = (char *)malloc(0);
printf("p1 = %p\n", p1);
free(p1);
return 0;
}
デフォルトでは、1024バイトが割り当てられます。mallocのサイズを大きくすると、割り当てられるバイト数は1025増加します。
Reed Copseyの回答とmallocのmanページによると、私はテストするためにいくつかの例を書きました。そして、malloc(0)は常に一意の値を与えることがわかりました。私の例を見てください:
char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
puts("Got a null pointer");
else
puts("Got a valid pointer");
出力は「Got a valid pointer」ですptr
。これはnullではないことを意味します。
malloc(0)
有効なメモリアドレスを返します。その範囲は、メモリに割り当てられているポインタのタイプによって異なります。また、メモリ領域に値を割り当てることもできますが、これは使用されているポインタのタイプの範囲内である必要があります。割り当てられたメモリを解放することもできます。例を挙げて説明します。
int *p=NULL;
p=(int *)malloc(0);
free(p);
上記のコードはgcc
、Linuxマシンのコンパイラーで正常に動作します。32ビットコンパイラを使用している場合は、整数の範囲、つまり-2147483648〜2147483647の値を指定できます。文字にも同じことが当てはまります。宣言されたポインタのタイプが変更されると、値の範囲はmalloc
タイプキャストに関係なく変化することに注意してください。
unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);
p
符号なし整数として宣言されているため、charの値は0〜255になります。
malloc()
キャストについては何も知りません(実際には完全にCでは余分です)。の戻り値を逆参照すると、malloc(0)
未定義の動作が呼び出されます。
ここで誤った印象を修正するだけです。
artist = (char *) malloc(0);
二度と戻ることはありませんNULL
。とは異なりますartist = NULL;
。簡単なプログラムを書いて、と比較artist
してくださいNULL
。if (artist == NULL)
は偽でif (artist)
あり、真です。