Страницы

Поиск по вопросам

понедельник, 27 мая 2019 г.

Почему без ошибок выполняется этот код?

char * buf = (char*)calloc(0,0);
buf = "vygbubinon";
printf("%s
", buf);
Выводится "vygbubinon". Хотя по идее памяти выделено недостаточно


Ответ

Давайте последовательно рассмотрим предложения указанного вами фрагмента кода. В первом предложении
char * buf = (char*)calloc(0,0);
выделяется память нулевого размера. Согласно стандарту языка C (7.22.3 Memory management functions)
If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
То есть вы можете запрашивать выделение памяти нулевого размера, но результат будет зависеть от платформы, где компилируется и выполняется программа. Либо будет возвращено значение NULL, либо некоторый действительный адрес памяти, по которому однако вы не можете обращаться к объекту. Так что данное предложение корректно.
Далее в следующем предложении независимо от того, каков был результат предыдущего предложения (либо NULL, либо некоторый действительный адрес) указатель buf переприсваивается, и получает адрес первого символа строкового литерала "vygbubinon".
buf = "vygbubinon";
Строковые литералы имеют статическую память. Следовательно, указатель получает адрес первого символа данного строкового литерала, расположенного в статической области памяти. Память для строковых литералов резервируется компилятором на этапе компиляции. (Компиляторы обычно собирают все литералы, присутствующее в программе, в некоторый пул литералов.) Ничего некорректного в этом предложении нет. Единственная проблема, связанная с этим предложением состоит в том, что если в предыдущем предложении была выделена память, то вы уже не сможете ее удалить, так как адрес этой памяти за счет переприсвоения указателя был утерян. Произойдет утечка памяти, но никакой ошибки времени компиляции или времени выполнения не будет.
Ну, и, наконец, в этом предложении выводится на консоль данный литерал.
printf("%s
", buf);
Так что фрагмент кода совершенно корректный за исключением возможной утечки памяти, что представляет собой лишь логическую ошибку.

Комментариев нет:

Отправить комментарий