11317


某所で  
`p = malloc(n*sizeof(Type));`  
...  
`p = realloc(p, ++n*sizeof(Type));`  
...  
`free(p);`  
のようなコード（実際のコードではありません）を見かけたんですが、  
（今取り上げたい）問題はｎが０から始まるってことです。  
`malloc(0)`?と思ったので、ちょっと調べて見ました。  
Ｃ９９のドラフトによると、

> 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.

私の(貧弱な英語力での解釈、間違ってたら指摘下さい、＊以下同様)理解する所では、  
「もしサイズに０が要求された場合の動作は処理系定義であり、  
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はポインタで指す領域を開放する。ポインタがＮＵＬＬの場合は何もしない、ポインタが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または、使用不能の非ゼロポインタが返される（どちらが返されるかは処理系定義である）」  
ではなく  
そもそも「サイズ０が指定された場合の動作が処理系定義」であって、だから書いていない？

詳しい人論拠と共にどう考えるべきか(あるいは解釈が違う、別のところにこういう記述があるなど…)教えて下さい。


CC BY-SA 3.0
2015-06-14T00:43:35.527
11315
2015-06-14T01:36:21.457
5044
question
c
malloc(0)のreallocの挙動


実際[Visual C++のmalloc](https://msdn.microsoft.com/ja-
jp/library/6ewkz86d.aspx)は後者の実装になっているようですね。

> size が 0 の場合、malloc 関数はヒープに長さが 0 のアイテムを割り当て、そのアイテムへの有効なポインターを返します。

reallocの第１引数は「アクセスできないような非ゼロのポインタ」だとしても「malloc,calloc,reallocで返されたポインタ」は満たしているわけですから問題ないように思います。


CC BY-SA 3.0
2015-06-14T01:20:28.663
11316
2015-06-14T01:20:28.663
4236
11315
answer


もうすこし正確に翻訳してみました。

> 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.  
>  
>  NULLポインタを返すか、もしくは返されたポインタがオブジェクトへのアクセスに使えないことを除けば、サイズに０以外が要求されたように動作する。

アクセスできないこと以外は`malloc`の引数に0以外のサイズを渡したときの戻り値と同じと言っているわけですから、`realloc`の引数に渡すことはなんの問題もありません。


CC BY-SA 3.0
2015-06-14T01:36:21.457
11317
2015-06-14T01:36:21.457
3639
11315
answer