34

callocのような 1 つではなく 2 つの引数を取るのはなぜmallocですか?

具体的には、次の式の間に違いがない (またはある?) ため:

calloc (a, b);
calloc (b, a);
calloc (a * b, 1);
calloc (1, a * b);

割り当てるバイトの総数を受け入れないのはなぜですか? このインターフェイスの背後にある理論的根拠は何ですか? そして、これが malloc に適用されないのはなぜですか?

4

5 に答える 5

12

引数が 2 つある理由について、2 つの [相互に排他的な] 説明を聞きました。

  1. calloc乗算のオーバーフローをチェックする責任を負います。要求されたブロックの合計サイズが大きすぎる場合 (overflows などsize_t)、calloc失敗を示すために null ポインターを返します。オーバーフローを自分で監視するmalloc必要がありますが、多くの人はそれを忘れています。(ただし、標準ライブラリの歴史では、callocオーバーフローを無視したために正しく機能しなかった実装の例が知られています)。

  2. calloc実際には、 type の範囲よりも大きなメモリ ブロックを割り当てることができますsize_t。つまりcalloc、引数のオーバーフローしない適切な大きな乗算を実行し、結果のサイズのブロックを割り当てることができる場合があります。このため、callocは type の 2 つの引数を使用するため、これまでsize_tよりも大きなブロックを割り当てることができます ( type の引数を 1 つしかとらないため)。mallocmallocsize_t

私は常に最初の説明が正しいと信じていました。ただし、ここでいくつかの投稿を読んだ後、私は疑問を持っています。

于 2010-11-03T03:11:57.710 に答える
4

malloc は、2 番目の引数で示されるサイズと互換性のある最も粗い要件に従って整列されたメモリ領域を返すことが保証されていると思います。たとえば、システムで 2 バイトおよび 4 バイトの整数の位置合わせが必要で、2 番目の引数が 10 の場合、返されるポインターは 2 バイト境界で位置合わせする必要があります。2 番目の引数が 12 の場合、ポインターは 4 バイト境界に位置合わせされます。実際には、多くのシステムが返されたすべてのポインターを、サイズに関係なく、必要とされる可能性のある最大の境界に揃えると思いますが、calloc 以外は必要ないと思います。

于 2010-11-03T03:27:40.807 に答える
0

calloc(x,y)と同等ですmalloc(x*y)

しかしcalloc、追加を行う(値を0に設定する)memset(block, 0, x*y)

この関数は、要素のサイズと要素をきれいに渡すためだけのものです.mallocで必要なバイト数を取得するためにこの値を乗算する必要がある場合、この関数は乗算で整数オーバーフローもチェックします.

たとえば、12 個の整数にメモリを割り当てたい場合、およびこの整数を使用して何かを実行したい場合、値を 0 に設定しておく必要があります。calloc(12, sizeof(int))

ただし、メモリ ブロック (256 バイト) を割り当てて、将来それにいくつかの文字列をコピーする場合memsetは、使用できません。より適切な使用法はmalloc(sizeof(char) * 256)、たとえばmalloc(sizeof(wchar_t) * 256)


void *
calloc (size_t nmemb, size_t lsize)
{
  void *ptr;
  struct __meminfo *info;
  size_t size = lsize * nmemb;

  /* if size overflow occurs, then set errno to ENOMEM and return NULL */
  if (nmemb && lsize != (size / nmemb))
    {
      set_errno (ENOMEM);
      return NULL;
    }

  /* allocate memory */
  ptr = malloc (size);

  /* get pointer to info part of chunk */
  info = __mem2info (ptr);

  /* fill memory with zeros and set __MEM_CALLOC flag */
  memset (ptr, 0, info->size);
  info->flags |= __MEM_CALLOC;

  return ptr;                   /* happy end */
}
于 2010-11-03T03:06:28.510 に答える
0

唯一の注目すべき違いはcalloc、割り当てられたスペースをゼロに初期化する必要があることですが、 ではそのような保証はありませんmalloc。そうでなければ、歴史的な理由から、2 つの異なる機能があると思います。

于 2010-11-03T03:07:21.647 に答える
0

Everything is just bytes は比較的新しい (つまり、c/Unix 時代の) 発明です。他の多くのアーキテクチャでは、固定サイズのレコードでした。

于 2010-11-03T03:07:34.467 に答える