malloc(0)のreallocの挙動
某所で
p = malloc(n*sizeof(Type));
...
p = realloc(p, ++n*sizeof(Type));
...
free(p);
のようなコード(実際のコードではありません)を見かけたんですが、
(今取り上げたい)問題はnが0から始まるってことです。
malloc(0)
?と思ったので、ちょっと調べて見ました。
C99のドラフトによると、
7.20.3 Memory management functions 1
... If the size of the space requested is zero, the behavior is
implementationdefined: either a null pointer is returned, or the
behavior is as if the size were some nonzero value, except that the
returned pointer shall not be used to access an object.
私の(貧弱な英語力での解釈、間違ってたら指摘下さい、*以下同様)理解する所では、
「もしサイズに0が要求された場合の動作は処理系定義であり、
NULLポインタ または オブジェクトメモリブロックとしてはアクセスできないような非ゼロのポインタが返される。」
また、freeの動作は、
The free function causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation. If ptr is
a null pointer, no action occurs. Otherwise, if the argument does not
match a pointer earlier returned by the calloc, malloc, or realloc
function, or if the space has been deallocated by a call to free or
realloc, the behavior is undefined.
「freeはポインタで指す領域を開放する。ポインタがNULLの場合は何もしない、ポインタがmalloc,calloc,reallocで返されたポインタでない場合、またはfree,reallocによって既に解放された領域の場合の動作は未定義」
そして、realloc の動作
The realloc function deallocates the old object pointed to by ptr and
returns a pointer to a new object that has the size specified by size.
The contents of the new object shall be the same as that of the old
object prior to deallocation, up to the lesser of the new and old
sizes. Any bytes in the new object beyond the size of the old object
have indeterminate values.
If ptr is a null pointer, the realloc
function behaves like the malloc function for the specified size.
Otherwise, if ptr does not match a pointer earlier returned by the
calloc, malloc, or realloc function, or if the space has been
deallocated by a call to the free or realloc function, the behavior is
undefined. If memory for the new object cannot be allocated, the old
object is not deallocated and its value is unchanged.
「realloc関数は古い領域を開放し指定されたサイズの新しい領域を指すポインタを返す。…もしもポインタがNULLの場合にはmallocの様に動作する。もしポインタがmalloc,calloc,reallocで返されたポインタでない場合、またはfree,reallocによって既に解放された領域の場合の動作は未定義。…」
ということで前置きが長くなりましたが、
malloc(0)
の場合、NULLまたは、使用不能の非ゼロポインタが返される(どちらが返されるかは処理系定義である)
ということで、
malloc(0)
がNULL
を返した場合には特に問題は無いと思います。
私が気になったのは、「使用不能の非ゼロポインタが返される」の場合。
freeは、mallocが返した値のポインタを解放する、とあって問題ないけれども、
realloc は、「使用不能の非ゼロポインタが返されたの場合」について動作が既定されていないように思う。
個人的にはNULL
の場合と同様の動作をするとすべきと思うがそこには含まれていない。
(新しい領域が確保された際にfreeされるという動作?)
malloc系の返値以外の場合は未定義とすることから暗にmalloc系の返値は受け入れるという主張があるとも言えると思うけども・。
というか、
「NULLまたは、使用不能の非ゼロポインタが返される(どちらが返されるかは処理系定義である)」
ではなく
そもそも「サイズ0が指定された場合の動作が処理系定義」であって、だから書いていない?
詳しい人論拠と共にどう考えるべきか(あるいは解釈が違う、別のところにこういう記述があるなど…)教えて下さい。