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

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

113 голосов
/ 07 января 2010

Только что увидел код:

artist = (char *) malloc(0);

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

Ответы [ 17 ]

116 голосов
/ 07 января 2010

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

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

artist = NULL;
48 голосов
/ 07 января 2010

Стандарт C (C17 7.22.3 / 1) гласит:

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

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

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

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

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

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

10 голосов
/ 07 января 2010

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

Обычно он возвращает указатель, который является действительным и уникальным, но НЕ ДОЛЖЕН разыменовываться. Также обратите внимание, что он МОЖЕТ потреблять память, даже если фактически ничего не выделял.

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

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

5 голосов
/ 16 апреля 2014

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

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

3 голосов
/ 16 апреля 2014

Здесь много наполовину правдивых ответов, так что вот неопровержимые факты. Страница руководства для malloc() говорит:

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

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

Если ptr равен NULL, никакие операции не выполняются.

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

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

3 голосов
/ 07 января 2010

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

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

2 голосов
/ 13 февраля 2015

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

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

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

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 Coding Standards, где я взял приведенный выше пример для дальнейшего чтения.

2 голосов
/ 25 января 2010

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

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

Надеюсь, это поможет, С наилучшими пожеланиями, Том.

1 голос
/ 24 января 2013

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

0 голосов
/ 23 октября 2015

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

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

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