что делает malloc (0) возврат? [дубликат]

Этот вопрос уже имеет ответ здесь:

Что делает malloc(0) возвраты? Был бы ответ быть тем же для realloc(malloc(0),0) ?

#include
#include
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
#include
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;
}
53
задан manav m-n 21 August 2015 в 20:20
поделиться

9 ответов

Другие ответили, как работает malloc (0) . Я отвечу на один из вопросов, которые вы попросили, которые еще не ответили (я думаю). Вопрос о Realloc (Malloc (0), 0) :

Что делает MALLOC (0) Будет ли ответ одинаковым для Realloc (malloc (0), 0) ?

Стандарт говорит о Realloc (PTR, размер) :

  • , если PTR - это NULL , он ведет себя как malloc (размер) ,
  • иначе ( PTR не NULL ), Он освободил старого указателя объекта на PTR PTR и возвращает указатель на новый выделенный буфер. Но если размер 0, C89 говорит, что эффект эквивалентен свободно (PTR) . Интересно, что я не могу найти это заявление в C99 Draft (N1256 или N1336). В C89 единственное разумное значение для возврата в этом случае будет NULL .

Итак, есть два случая:

  • MALLOC (0) возвращает NULL на реализации. Тогда ваш Realloc () вызов эквивалентен Realloc (NULL, 0) . Это эквивалентно malloc (0) сверху (и то есть null в этом случае).
  • MALLOC (0) возвращает NULL NULL . Затем вызов эквивалентен бесплатно (Malloc (0)) . В этом случае Malloc (0) и Realloc (malloc (0), 0) не эквивалентны .

Обратите внимание, что здесь есть интересный случай: во втором случае, когда Malloc (0) возвращает не- NULL на успехе, он все еще может вернуться NULL Чтобы указать сбой. Это приведет к тому, как вызов: RealLoc (NULL, 0) , который был бы эквивалентен Malloc (0) , что может не возвращать NULL Отказ

Я не уверен, что упущение в C99 является надзором или если это означает, что в C99, Realloc (PTR, 0) для не- NULL PTR Не эквивалентно бесплатно (PTR) . Я только что попробовал это с GCC -Std = C99 , а вышеизложенное эквивалентно бесплатно (PTR) .

Редактировать : Я думаю, что я понимаю, что ваша путаница:

Давайте посмотрим на фрагмент из вашего примерного кода:

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

Вышеупомянутое не совпадает с malloc (0) == Realloc (Malloc (0), 1024) . Во-вторых, Call () Call () Call () вызов выполнен дважды, тогда как в первую очередь вы передаете ранее выделенный указатель на Realloc () .

Давайте сначала проанализируем первый код. Предполагая malloc (0) не возвращает null на успехе, PTR имеет допустимое значение. Когда вы делаете Realloc (PTR, 1024) , Realloc () в основном дает вам новый буфер, имеющий размер 1024, а PTR становится недействительным. Соответствующая реализация может вернуть тот же адрес, что и тот, который уже в PTR . Итак, ваш , если состояние может вернуть истину. (Обратите внимание, однако, глядя на значение PTR после Realloc (PTR, 1024) может быть неопределенным поведением.)

Теперь вопрос, который вы спрашиваете: Malloc ( 0) == Realloc (Malloc (0), 1024) . В этом случае давайте предположим, что как Malloc (0) как (0) на LHS и RHS NULL NULL . Затем они гарантированно будут разными. Кроме того, возвращаемое значение из malloc () на LHS не было Free () d пока, так что любой другой malloc () , Calloc () или Realloc () может не вернуть это значение. Это означает, что если вы написали свое состояние как:

if (malloc(0) == realloc(malloc(0), 1024)
    puts("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 он печатает , OK .

44
ответ дан 7 November 2019 в 08:34
поделиться

C99 Standard

Если пространство не может быть выделено, NullPointer возвращается. Если размер запрашиваемого пространства равен нулю, поведение определено в реализации: либо нулевой указатель возвращается или поведение, как будто размер были некоторая ненулевая ценность, за исключением того, что Возвращенный указатель не должен использоваться для Доступ к объекту.

5
ответ дан 7 November 2019 в 08:34
поделиться

PAQ COMP.LANG.C имеет следующее , чтобы сказать:

Стандарт ANSI / ISO говорит, что это может делать либо; поведение Определен в реализации (см. вопрос 11.33). Портативный код должен либо заботиться, чтобы не звонить в Malloc (0), либо быть подготовлен к возможности нулевой возвращаться.

Итак, вероятно, лучше всего избегать использования Malloc (0) .

5
ответ дан 7 November 2019 в 08:34
поделиться

Это зависит от того, что вы пытаетесь сделать. Если вы просто хотите создать POMS для новых проектов определенного типа, лучший путь - через Maven Archetypes (вы можете создавать свои собственные архетипы с помощью хоченных вами шаблонов).

Если у вас действительно есть необходимость программно написать POM, вы можете использовать следующее:

import org.apache.maven.model.*;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
...
Model model = new Model();
model.setGroupId( "some.group.id" );
...
new MavenXpp3Writer().write( w, model );

... где W - java.io.writer, и вы добавляете все необходимое обработку исключения.

JavadoC здесь: http://maven.apache.org/ref/2.2.1/maven-model/apidocs/index.html

Чтобы получить доступ к этому API, вы должны добавить эту зависимость:

<dependency>
  <groupId>org.apache.maven</groupId>
  <artifactId>maven-model</artifactId>
  <version>2.2.1</version>
</dependency>

Также имеется соответствующий прочитанный API, но имею в виду, что он не будет делать все операции Maven, таких как наследование и интерполяция (для этого требует более распространенного использования API).

-121--2570777-

Malloc (0) представляют собой Определен реализацией , насколько касается C99.

Из C99 [Раздел 7.20.3]

Орден и смежность хранения, выделенные последовательными вызовами в Calloc, Malloc, и функции Realloc невыразится . Указатель вернулся, если распределение Успешные успехи соответственно выровнены, чтобы его можно было назначить указателю на любой тип объекта а затем используется для доступа к такому объекту или на массиве таких объектов в пространстве, выделенном (до тех пор, пока пространство явно отделено). Срок службы выделенного объекта расширяется от выделения до освобождения. Каждое такое распределение должно приносить указатель на объект не пересекается из любого другого объекта. Указатель вернул точки до начала (самый низкий байт адрес) выделенного пространства. Если пространство не может быть выделено, нулевой указатель вернулся. Если размер запрошенного пространства равен нулю, поведение является реализацией определяется : возвращается либо нулевой указатель, либо поведение, как если бы размер был некоторый ненулевое значение, за исключением того, что возвращенный указатель не должен использоваться для доступа к объекту.

33
ответ дан 7 November 2019 в 08:34
поделиться

См. C99, раздел 7.20.3:

Если размер запрашиваемого пространства ноль, поведение Реализация определяется: либо нуль Указатель возвращен или поведение как будто размер был какой-то ненулевой значение, за исключением того, что возвращенные Указатель не должен использоваться для доступа к объект.

Это действительно для всех трех функций распределения (то есть Calloc () , malloc () и Realloc () ).

3
ответ дан 7 November 2019 в 08:34
поделиться

Если malloc(0) возвращает фиктивный указатель, то как это работает:

void *ptr = malloc(0);

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

Я не знаю, что вы имеете в виду под "фиктивным указателем". Если malloc(0) возвращает nonNULL, то ptr является действительным указателем на блок памяти нулевого размера. Реализация malloc сохраняет эту информацию в специфическом для данной реализации виде. Реалок realloc знает (специфический для реализации) способ выяснить, что ptr указывает на блок памяти с нулевым значением.

(Как malloc/realloc/free делают это специфично для реализации. Одна из возможностей - выделить на 4 байта больше, чем запрошено, и записать размер непосредственно перед блоком памяти. В этом случае ((int *)ptr)[-1] выдаст размер блока памяти, который составляет 0. Этого никогда не следует делать из своего кода, он только для использования realloc и free).

0
ответ дан 7 November 2019 в 08:34
поделиться

В C89 Malloc (0) зависит от реализации - я не знаю, если C99 исправил это или нет. В C ++ используют:

char * p = new char[0];

хорошо определен - вы получаете действительный, ненулкий указатель. Конечно, вы не можете использовать указатель для доступа к тому, что он указывает, не вызывая неопределенного поведения.

Что касается того, почему это существует, для некоторых алгоритмов удобно, а значит, что вам не нужно помещать свой код тестами на нулевые значения.

15
ответ дан 7 November 2019 в 08:34
поделиться

Один момент, о котором пока никому не интересно говорить, в Вашей первой программе это то, что realloc с длиной 0 - то же самое, что free.

из man-страницы Solaris:

Функция realloc() изменяет размер блока, на который указывает на ptr до размера байтов и возвращает указатель на (возможно, перемещенный) блок. Содержимое будет неизменным вплоть до меньший из новых и старых размеров. Если ptr равен NULL, realloc(). ведет себя как malloc() для указанного размера. Если размер равен 0. и ptr не является нулевым указателем, указанное пробело сделано доступный для дальнейшего распределения по заявке, однако не вернулся в систему. Память возвращается в систему только по окончании срока действия заявления.

Если не знать, что это может стать причиной плохого сюрприза (случилось со мной).

3
ответ дан 7 November 2019 в 08:34
поделиться

Я думаю, что это зависит. Я проверил источники Visual Studio 2005 и увидел это в функции _HEAP_ALLOC:

if (size == 0)
    size = 1;

Я думаю, что во многих случаях вы можете захотеть действительный указатель, даже при просим нулевых байтов. Это связано с тем, что это согласованное поведение облегчает проверку ваших указателей, потому что: если у вас нет нулевой указатель, все в порядке; Если у вас есть нулевой указатель, у вас, вероятно, есть проблема. Вот почему я думаю, что большинство реализаций вернут действительный указатель даже при просях нулевых байтов.

2
ответ дан 7 November 2019 в 08:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: