какой смысл в malloc(0)?


только что видел этот код:

artist = (char *) malloc(0);

и мне было интересно, зачем это делать?

16 102

16 ответов:

согласно спецификации, malloc (0) вернет либо " нулевой указатель, либо уникальный указатель, который может быть успешно передан в free()".

это в основном позволяет вам ничего не выделять, но все же передавать переменную "artist" в вызов free() без беспокойства. Для практических целей это почти то же самое, что делать:

artist = NULL;

стандарт C говорит:

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

и malloc(0) может вернуться NULL или допустимый указатель этого может и не быть разыменованный. В любом случае, это совершенно справедливо, чтобы позвонить free() на нем.

не думаю malloc(0) имеет много пользы, за исключением случаев, когда malloc(n) вызывается в цикле, например, и n может быть ноль.

глядя на код в ссылке, я считаю, что у автора было два заблуждения:

  • malloc(0) возвращает допустимый указатель всегда и
  • free(0) is плохой.

Итак, он убедился, что artist и другие переменные всегда имели некоторое "действительное" значение в них. В комментарии говорится так же:// these must always point at malloc'd data.

поведение malloc(0) является специфичным для реализации. Библиотека может возвращать NULL или иметь обычное поведение malloc, без выделения памяти. Что бы он ни делал, это должно быть где-то задокументировано.

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

можно перераспределить ненулевой указатель malloc(0).

имея a Маллок (0) дословно не очень много пользы, хотя. Он в основном используется, когда динамическое распределение является нулевым байтом, и вы не хотели его проверять.

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

делаешь что malloc(0) будет не автоматически выделять память правильного размера. Функция malloc не знает, что вы бросая свой результат к. Функция malloc полагается исключительно на номер размера, который вы даете в качестве аргумента. Вам нужно сделать malloc(sizeof (int)), чтобы получить достаточно места для хранения int, например, а не 0.

есть много половины истинные ответы здесь, поэтому здесь представлены неопровержимые факты. Человек-страница для malloc() говорит:

если size равен 0, то malloc () возвращает либо NULL, либо уникальное значение указателя, которое позже может быть успешно перешел на free ().

это означает, что нет абсолютно никакой гарантии, что результат malloc(0) является либо уникальным, либо не нулевым. Единственная гарантия предоставляется по определению free() опять же, вот что человек-страница говорит:

если ptr имеет значение NULL, операция не выполняется.

так, что malloc(0) возвращает, его можно безопасно передать в free(). Но так может NULL указатель.

следовательно, писатьartist = malloc(0);это ни в коем случае не лучше, чем писатьartist = NULL;

malloc(0) не имеет никакого смысла для меня, если код не зависит от поведения, специфичного для реализации. Если код должен быть переносимым, то он должен учитывать тот факт, что нулевой возврат из malloc(0) Это не провал. Так почему бы просто не присвоить NULL artist в любом случае, так как это действительный успешный результат, и меньше кода, и не заставит ваших программистов обслуживания занять время, выясняя это?

malloc(SOME_CONSTANT_THAT_MIGHT_BE_ZERO) или malloc(some_variable_which_might_be_zero) возможно, могли бы их использовать, хотя опять же вы должны проявлять особую осторожность, чтобы не рассматривать нулевое возвращение как сбой, если значение равно 0, но размер 0 должен быть в порядке.

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

  • foo не является нулем, а размер равен нулю,realloc(foo, size);. Когда вы передаете ненулевой указатель и размер нуля в realloc, realloc ведет себя так, как если бы вы вызвали free(...)
  • функция Foo имеет значение null а размер ненулевой и больше 1,realloc(foo, size);. Когда вы передаете нулевой указатель и размер не равен нулю, realloc ведет себя так, как если бы вы вызвали malloc(...)

надеюсь, это поможет, С уважением, Том.

чтобы на самом деле ответить на вопрос сделал: нет никаких причин делать это

почему вы не должны делать этого...

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

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

size_t size;

/* Initialize size, possibly by user-controlled input */

int *list = (int *)malloc(size);
if (list == NULL) {
  /* Handle allocation error */
}
else {
  /* Continue processing list */
}

посмотреть эта безопасная страница кодирования из стандартов кодирования CERT, где я взял пример выше для дальнейшего чтения.

Не уверен, по некоторым данным случайный источник malloc код, который я нашел, ввод 0 приводит к возвращаемому значению NULL. Так что это сумасшедший способ установить указатель художника на NULL.

http://www.raspberryginger.com/jbailey/minix/html/lib_2ansi_2malloc_8c-source.html

malloc (0) вернет NULL или допустимый указатель, который может быть правильно передан в free. И хотя кажется, что память, на которую он указывает, бесполезна или ее нельзя записать или прочитать, это не всегда верно. :)

int *i = malloc(0);
*i = 100;
printf("%d", *i);

мы ожидаем ошибки сегментации здесь, но удивительно, что это печатает 100! Это потому, что Мэллок на самом деле просит огромный кусок памяти, когда мы называем Мэллок в первый раз. Каждый вызов malloc после этого использует память из этого большого куска. Только после того, как этот огромный кусок закончился, запрашивается новая память.

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

В Windows:

  • void *p = malloc(0); выделит буфер нулевой длины в локальной куче. Возвращенный указатель является допустимым указателем кучи.
  • malloc в конечном счете называет HeapAlloc используя кучу времени выполнения C по умолчанию, которая затем вызывает RtlAllocateHeap и т. д.
  • free(p); использует HeapFree чтобы освободить буфер 0-длины в куче. Не освобождая его приведет к утечке памяти.

вот анализ после запуска с valgrind memory check tool.

==16740== Command: ./malloc0
==16740==
p1 = 0x5204040
==16740==
==16740== HEAP SUMMARY:
==16740==     in use at exit: 0 bytes in 0 blocks
==16740==   total heap usage: 2 allocs, 2 frees, 1,024 bytes allocated
==16740==
==16740== All heap blocks were freed -- no leaks are possible

и вот мой пример кода:

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

int main()
{
   //int i;
   char *p1;

   p1 = (char *)malloc(0);
   printf("p1 = %p\n", p1);

   free(p1);

   return 0;

}

по умолчанию выделяется 1024 байта. Если я увеличу размер malloc, выделенные байты увеличатся на 1025 и так далее.

по данным Рид Copsey ответ и man-страница malloc, я написал несколько примеров для тестирования. И я узнал, что malloc (0) всегда будет давать ему уникальное значение. Смотрите мой пример:

char *ptr;
if( (ptr = (char *) malloc(0)) == NULL )
    puts("Got a null pointer");
else
    puts("Got a valid pointer");

вывод будет "получил действительный указатель", что означает ptr не null.

malloc(0) возвращает действительный адрес памяти и диапазон которого будет зависеть от типа указателя, который выделяется память. Также вы можете присвоить значения области памяти, но это должно быть в диапазоне с типом используемого указателя. Вы также можете освободить выделенную память. Я объясню это на примере:

int *p=NULL;
p=(int *)malloc(0);
free(p);

приведенный выше код будет работать нормально в gcc компилятор на Linux-машине. Если у вас есть 32-битный компилятор, то вы можете задать значения в целое число диапазон, т. е. от -2147483648 до 2147483647. То же самое относится и к персонажам. Обратите внимание, что если тип объявленного указателя изменяется, то диапазон значений будет меняться независимо от malloc typecast, т. е.

unsigned char *p=NULL;
p =(char *)malloc(0);
free(p);

p будет принимать значение от 0 до 255 char, так как он объявлен без знака int.

просто, чтобы исправить ложное впечатление здесь:

artist = (char *) malloc(0); никогда не вернуться NULL, это не то же самое как artist = NULL;. Напишите простую программу и сравните artist С NULL. if (artist == NULL) false и if (artist) - это правда.