Разница между инициализацией строки с помощью (char *)malloc(0) и NULL

Почему в этом случае работает выделение блока char размера 0? Но если я напишу char *string = NULL;, это не сработает.

Я использую Visual Studio.

int main()
{   
    char *string = (char *)malloc(0);
    string[0] = 'a';
    string[1] = 'b';
    string[2] = 'c';
    string[3] = 'd';
    string[4] = '\0';

    printf("%s\n",string);
    return 0;
}

person Viktor Simkó    schedule 06.08.2015    source источник
comment
Это не работает; в лучшем случае делает вид, что работает. Неопределенное поведение называется неопределенным и не гарантированным сбоем по очень веской причине.   -  person The Paramagnetic Croissant    schedule 06.08.2015
comment
Чего вы ожидали и почему?   -  person M.M    schedule 06.08.2015
comment
Это вовсе не дубликат.   -  person Sourav Ghosh    schedule 06.08.2015
comment
Пожалуйста, не используйте результат malloc().   -  person Quentin    schedule 06.08.2015
comment
возможный дубликат индекса массива вне границ в C   -  person Bo Persson    schedule 06.08.2015
comment
Это точно не дубликат.   -  person Mauker    schedule 06.08.2015


Ответы (3)


Сначала позвольте мне указать, как указано на справочной странице malloc()

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

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

  • Возврат NULL
  • Возвращает указатель, который можно передать free().

но в любом случае разыменование этого указателя не допускается. Это вызовет неограниченный доступ к памяти и вызовет неопределенное поведение.

Тем не менее, две важные вещи, чтобы упомянуть,

  1. Пожалуйста, узнайте, почему бы не привести возвращаемое значение malloc() и семьи в C.

  2. Пожалуйста, проверьте возвращаемое значение malloc() перед использованием возвращенного указателя.

Итак, чтобы ответить на ваш вопрос,

Разница между инициализацией строки с помощью (char *)malloc(0) и NULL

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

person Sourav Ghosh    schedule 06.08.2015

Приведенный выше код вызывает неопределенное поведение. Вы выделили недостаточно памяти и обращаетесь к недопустимым адресам.

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

person Sadique    schedule 06.08.2015
comment
s/random/invalid. Поведение распределителя памяти довольно неслучайно, это сделало бы ужасный PRNG. - person The Paramagnetic Croissant; 06.08.2015
comment
@Quentin, но это сайт вопросов и ответов для программистов, и если кто-то дает ответ, он должен правильно его сформулировать. С тем же успехом я мог бы решить, что с этого момента я использую слово «строка» для обозначения функции, а затем я жалуюсь каждый раз, когда кто-то указывает, что нельзя вызвать строку, которую я просто использую как строку с функцией в качестве ее значения. Некоторые люди пытаются использовать адреса выделения памяти в качестве источника случайных чисел. Давайте не будем поощрять распространение инфекции (а что, если эти случайные числа закончат шифрованием вашего HTTPS-трафика? Вам это нравится?) - person The Paramagnetic Croissant; 06.08.2015
comment
@Квентин подрасти. серьезно, если вы не видите ценности в правильной формулировке того, что говорите, я даже не хочу с вами дальше спорить. - person The Paramagnetic Croissant; 06.08.2015
comment
@ThePara MagneticCroissant Я даже не понимаю, почему вы вообще спорите. Конечно, недействительный лучше, чем случайный для неопределенного адреса. Просто мысль о том, что кто-то ухватится за простое присутствие слова random и попытается сделать из него PRNG, заставила меня усмехнуться. Нет причин расстраиваться. - person Quentin; 06.08.2015

malloc определение:

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

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

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

Взято из здесь и найдено этот связанный вопрос.

person Mauker    schedule 06.08.2015
comment
вызов malloc(0) не приводит к неопределенному поведению, и возвращаемый адрес также не является случайным. (в частности, он должен быть уникальным.) - person The Paramagnetic Croissant; 06.08.2015