56

何をmalloc(0)返しますか?

の答えは同じrealloc(malloc(0),0)でしょうか?

#include<stdio.h>
#include<malloc.h>
int main()
{
        printf("%p\n", malloc(0));
        printf("%p\n", realloc(malloc(0), 0));
        return 0;
}

Linux GCC からの出力:

manav@manav-workstation:~$ gcc -Wall mal.c
manav@manav-workstation:~$ ./a.out
0x9363008
(nil)
manav@manav-workstation:~$

の出力は毎回変化し続けmalloc(0)ます。これは標準的な答えですか?そして、学術研究以外で、なぜそのようなポインターを取得することに興味があるのでしょうか?

編集:

ダミー ポインターを返す場合malloc(0)、次はどのように機能しますか。

int main()
{
    void *ptr = malloc(0);
    printf("%p\n", realloc(ptr, 1024));
    return 0;
}

編集:

次のコードは、反復ごとに「可能」を出力します。なぜ失敗してはいけないのですか?

#include<stdio.h>
#include<malloc.h>
int main()
{

        int i;
        void *ptr;
        printf("Testing using BRUTE FORCE\n");
        for (i=0; i<65000; i++)
        {
                ptr = malloc(0);
                if (ptr == realloc(ptr, 1024))
                        printf("Iteration %d: possible\n", i);
                else
                {
                        printf("Failed for iteration %d\n", i);
                        break;
                }
        }
        return 0;
}
4

9 に答える 9

44

他の人はどのように機能するかを答えmalloc(0)ました。あなたが尋ねた、まだ答えられていない質問の1つに答えます(と思います)。質問は次のrealloc(malloc(0), 0)とおりです。

何をmalloc(0)返しますか?の答えは同じrealloc(malloc(0),0)でしょうか?

標準はこれについて次のように述べていrealloc(ptr, size)ます:

  • の場合、次のようptrNULL動作しますmalloc(size)
  • それ以外の場合 ( ptris not NULL)、by への古いオブジェクト ポインターの割り当てを解除ptrし、新しく割り当てられたバッファーへのポインターを返します。しかし、sizeが 0 の場合、C89 は効果が と同等であると言いfree(ptr)ます。興味深いことに、C99 ドラフト (n1256 または n1336) でそのステートメントを見つけることができません。C89 では、その場合に返される唯一の適切な値は ですNULL

したがって、次の 2 つのケースがあります。

  • malloc(0)実装を返しますNULL。次に、realloc()呼び出しは と同等realloc(NULL, 0)です。malloc(0)これはfrom aboveと同等です (NULLこの場合はそうです)。
  • malloc(0)返品不可NULL。次に、呼び出しは と同等free(malloc(0))です。この場合、malloc(0)realloc(malloc(0), 0)は等価ではありません。

ここで興味深いケースがあることに注意してください: 2 番目のケースでは、成功以外をmalloc(0)返す場合でも、失敗を示すために返される場合があります。これは次のような呼び出しになります: と同等で、 を返す場合と返さない場合があります。NULLNULLrealloc(NULL, 0)malloc(0)NULL

C99 での省略が見落としなのか、それとも C99 では、realloc(ptr, 0)for non-NULL ptrが と同等ではないことを意味するのかはわかりませんfree(ptr)。でこれを試したところgcc -std=c99、上記は と同等free(ptr)です。

編集:私はあなたの混乱が何であるかを理解していると思います:

サンプル コードのスニペットを見てみましょう。

ptr = malloc(0);
if (ptr == realloc(ptr, 1024))

上記は と同じではありませんmalloc(0) == realloc(malloc(0), 1024)。2 番目では、malloc()呼び出しが 2 回行われますが、最初の呼び出しでは、以前に割り当てられたポインターを に渡していますrealloc()

最初のコードを最初に分析しましょう。成功malloc(0)しても返されないと仮定すると、有効な値があります。を実行すると、基本的にサイズが 1024 の新しいバッファが提供され、無効になります。適合する実装は、すでに にあるアドレスと同じアドレスを返す場合があります。したがって、条件が true を返す場合があります。(ただし、afterの値を見ると、未定義の動作になる可能性があることに注意してください。)NULLptrrealloc(ptr, 1024)realloc()ptrptrifptrrealloc(ptr, 1024)

今、あなたが尋ねる質問: malloc(0) == realloc(malloc(0), 1024). malloc(0)この場合、 LHS と RHS の両方の が non- を返すと仮定しましょうNULL。次に、それらは異なることが保証されます。また、malloc()LHSからの戻り値はfree()まだ d になっていないため、他のmalloc()calloc()、またはrealloc()はその値を返さない可能性があります。これは、条件を次のように記述した場合を意味します。

if (malloc(0) == realloc(malloc(0), 1024)
    puts("possible");

出力には表示possibleされません(両方malloc()realloc()失敗し、戻りしない限りNULL)。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    void *p1;
    void *p2;

    p1 = malloc(0);
    p2 = realloc(p1, 1024);
    if (p1 == p2)
        puts("possible, OK");

    /* Ignore the memory leaks */
    if (malloc(0) == realloc(malloc(0), 1024))
        puts("shouldn't happen, something is wrong");
    return 0;
}

OS X では、コードを実行しても何も出力されませんでした。Linux では、出力されpossible, OKます。

于 2010-01-25T20:16:54.627 に答える
34

malloc(0)C99に関する限り、実装定義です。

C99から[セクション 7.20.3]

calloc、malloc、および realloc 関数への連続した呼び出しによって割り当てられるストレージの順序と連続性 は規定されていません。割り当てが成功した場合に返されるポインターは、任意の型のオブジェクトへのポインターに割り当てられ、割り当てられた空間内のそのようなオブジェクトまたはそのようなオブジェクトの配列にアクセスするために使用されるように適切に整列されます (空間が明示的に割り当て解除されるまで)。 . 割り当てられたオブジェクトの有効期間は、割り当てから解放まで延長されます。そのような各割り当ては、他のオブジェクトから切り離されたオブジェクトへのポインタを生成します。返されるポインタは、割り当てられた空間の開始 (最下位バイト アドレス) を指します。スペースを割り当てることができない場合は、ヌル ポインターが返されます。 要求されたスペースのサイズがゼロの場合、動作は実装定義です。null ポインターが返されるか、サイズがゼロ以外の値であるかのように動作します。ただし、返されたポインターはオブジェクトへのアクセスには使用されません。 .

于 2010-01-25T12:53:23.797 に答える
15

C89 では、malloc(0) は実装依存です。C99 でこれが修正されたかどうかはわかりません。C++ では、以下を使用します。

char * p = new char[0];

明確に定義されています-有効な非nullポインターを取得します。もちろん、ポインターを使用して、未定義の動作を呼び出さずにポインターが指すものにアクセスすることはできません。

これが存在する理由については、一部のアルゴリズムにとって便利であり、ゼロ値のテストでコードを散らかす必要がないことを意味します。

于 2010-01-25T12:49:10.140 に答える
5

C99規格

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

于 2010-01-25T12:50:33.460 に答える
5

comp.lang.c FAQには、次のように書かれています。

ANSI/ISO 規格では、どちらでもかまいません。動作は実装定義です (質問 11.33 を参照)。移植可能なコードでは、malloc(0) を呼び出さないように注意するか、null が返される可能性に備えておく必要があります。

したがって、使用を避けるのがおそらく最善malloc(0)です。

于 2010-01-25T12:51:51.310 に答える
4

まだ誰も話したくない点の1つは、最初のプログラムではrealloc、長さが0の場合は。と同じであるということfreeです。

Solarisのマニュアルページから:

このrealloc()関数は、が指すブロックのサイズptrsizeバイトに変更し、(移動された可能性のある)ブロックへのポインターを返します。内容は新旧サイズの小さい方まで変更ありません。の場合、指定されたサイズの ように動作ptrします。 が ヌルポインタ で あり、ヌルポインタでない場合、ポイントされたスペースは、システムに戻されませんが、アプリケーションによる追加の割り当てに使用できるようになります。メモリは、アプリケーションの終了時にのみシステムに戻されます。NULLrealloc()malloc()size0ptr

それが悪い驚きの原因になり得ることを知らない場合(私に起こった)。

于 2010-01-25T15:41:29.580 に答える
3

C99 のセクション 7.20.3 を参照してください。

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

calloc()これは、3 つの割り当て関数 ( 、malloc()および)のすべてに有効ですrealloc()

于 2010-01-25T12:53:29.263 に答える
2

依存していると思います。Visual Studio 2005 のソースを確認したところ、_heap_alloc 関数で次のことがわかりました。

if (size == 0)
    size = 1;

多くの場合、ゼロバイトを要求する場合でも、有効なポインターが必要になると思います。これは、この一貫した動作により、ポインターのチェックが容易になるためです。NULL 以外のポインターがあれば問題ありません。NULL ポインターがある場合は、おそらく問題があります。そのため、ゼロバイトを要求した場合でも、ほとんどの実装は有効なポインターを返すと思います。

于 2010-01-25T12:54:20.143 に答える
0

malloc(0) がダミー ポインターを返す場合、次のように動作します。

void *ptr = malloc(0);

printf("%p\n", realloc(ptr, 1024));

「ダミーポインター」の意味がわかりません。malloc(0)NULL 以外を返す場合はptr、サイズ 0 のメモリ ブロックへの有効なポインタです。実装は、このmalloc情報を実装固有の方法で保存します。 サイズがゼロのメモリブロックを指しているreallocことを理解する(実装固有の)方法を知っています。ptr

(どのようにmalloc//これを行うreallocfreeは実装固有です。1 つの可能性は、要求されたよりも 4 バイト多く割り当て、メモリ ブロックの直前にサイズを格納することです。その場合、((int *)ptr)[-1]はメモリ ブロック サイズを与えます。これは0です。決してこれを行うべきではありませんあなたのコードから、それは と によってのみ使用されますrealloc) free

于 2010-01-25T13:37:17.963 に答える