Ответ 1
От http://www.c-faq.com/malloc/realloc.html
Если realloc вообще не может найти достаточно места, он возвращает нулевой указатель и оставляет выделенную ранее область.
Поэтому вам действительно нужно освободить ранее выделенную память.
Может ли кто-нибудь обобщить правильное использование realloc()
?
Что вы делаете, когда realloc()
терпит неудачу?
Из того, что я видел до сих пор, кажется, что если realloc()
терпит неудачу, вы должны использовать free()
старый указатель. Это правда?
Вот пример:
1. char *ptr = malloc(sizeof(*ptr) * 50);
2. ...
3. char *new_ptr = realloc(ptr, sizeof(*new_ptr) * 60);
4. if (!new_ptr) {
5. free(ptr);
6. return NULL;
7. }
Предположим, что realloc()
терпит неудачу в строке 3
. Правильно ли я делаю это на линии 5
на free()
ing ptr
?
От http://www.c-faq.com/malloc/realloc.html
Если realloc вообще не может найти достаточно места, он возвращает нулевой указатель и оставляет выделенную ранее область.
Поэтому вам действительно нужно освободить ранее выделенную память.
Это зависит от того, что вы хотите сделать. Когда realloc
выходит из строя, что вы хотите сделать: освободите старый блок или сохраните его в живых и не изменив? Если вы хотите освободить его, то освободите его.
Имейте в виду также, что в C89/90, если вы делаете запрос realloc
с нулевым размером цели, функция realloc
может возвращать нулевой указатель, даже если исходная память была успешно освобождена. Это был дефект в C89/90, так как не удалось сказать успех от отказа при нулевом возврате.
В C99 этот дефект был исправлен, и была гарантирована строгая связь между нулевым возвратом и успехом/неудачей перераспределения. В C99 нулевой возврат всегда означает полный сбой realloc
.
Если realloc не работает, я не думаю, что вы захотите удалить исходный блок, так как потеряете его. Похоже, что realloc изменит размер старого блока (или вернет указатель на новое место), и при успешном возвращении указатель на старый блок (или новое местоположение) и при ошибке вернет NULL. Если он не может выделить новый блок, старый блок не тронут.
Edit: Correction, некоторые люди избивают меня за то, что я сказал, то, как вы выделили свой указатель, кажется, это лучшая практика среди них, меня учили всегда идти с типом cast в sizeof()
, но, очевидно, ваш путь правильнее, поэтому не обращайте внимания на то, что я сказал =)
Взяв заглянуть в http://en.wikipedia.org/wiki/Malloc#realloc, вы, возможно, сделали вам что-то хорошее.
Вы не совсем понимаете sizeof()
- он имеет значение размера аргумента, передаваемого ему в байтах. Например, sizeof(int)
будет 4 в большинстве 32-битных систем, но вы должны использовать sizeof(int)
вместо 4
, потому что компиляция вашего кода в 64-битной системе (как пример) сделает это значение равным 8 и ваш код все равно будет компилироваться. Для чего вы выделяете память? Указатели? Если это так, вы должны использовать sizeof(void*)
вместо этого (вы можете сказать sizeof(int*)
, но это общепринятое соглашение не упоминать компилятору, что вы хотите сохранить в этих указателях, поскольку все указатели должны быть одного размера - поэтому большинство программистов говорят sizeof(void*)
), если вам нужно место для символов, используйте sizeof(char)
и т.д.
Однако вы правы, чтобы сохранить возвращаемое значение realloc()
в новом указателе и проверить его, хотя многие программисты предполагают, что система всегда имеет достаточно памяти и уходит с ней.