Вопрос об использовании реализации realloc в коде C++
-
06-07-2019 - |
Вопрос
Друзья
В нашем C++ я сейчас использую метод realloc для изменения размера памяти, выделенной malloc.Использование realloc() выполняется, как показано ниже.
my_Struct *strPtr =(my_struct*)malloc(sizeof(my_Struct));
/* an later */
strPtr = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR);
теперь википедия (_http://en.wikipedia.org/wiki/Malloc) говорит, что
Если бы вместо этого кто-то сделал
void *p = malloc(orig_size);
/* and later... */
p = realloc(p, big_size);
тогда в случае, если невозможно получить байты памяти big_size, p будет иметь значение NULL, и у нас больше не будет указателя на память, ранее выделенную для p, создавая утечку памяти
И там также говорится, что правильный способ исправить вышеуказанную ошибку:
void *p = malloc(orig_size);
/* and later... */
void *tmp = realloc(p, big_size);
if (tmp != NULL)
{
p = tmp; /* OK, assign new, larger storage to p */
}
else
{
/* handle the problem somehow */
}
Можете ли вы сказать мне, какой лучший способ использовать realloc()?
также, когда у меня есть указатель на структуру, а затем, используя realloc, могу ли я использовать указатель на пустоту ???
Большое спасибо
Решение
Конечно, вы должны защититься от случая, когда realloc()
возвращает NULL
.Это выделение памяти, и в C (где realloc()
) в основном используется, я думаю, что программисты C++ считают, что использовать необработанный код — это немного низкоуровнево/небрежно. realloc()
вызовы, выделение памяти всегда может завершиться неудачно.
Непосредственная перезапись указателя возвращаемым значением является ошибкой, поскольку при этом исходный указатель удаляется и происходит утечка памяти в случае неудачного перераспределения.
Другие советы
Malloc() и realloc() — это функции C.На самом деле, realloc() выполняет функции malloc() и free() в зависимости от переданных вами аргументов:
- Если вы передадите ему нулевой указатель, realloc сделает то же, что и malloc.
- Если вы передадите ему нулевой размер, realloc сделает то же, что и free.
Цитата: Здесь, где у вас есть более глубокое объяснение.
Библиотека C делает невозможным расширение блока памяти на месте, поэтому C++ его также не поддерживает.
Если вы хотите придерживаться функций C, вам следует удерживать указатель вашего первого выделения памяти при вызове realloc().Затем вы проверяете, имеет ли он значение NULL, в противном случае вы назначаете его, как и в своем последнем коде.
Но, возможно, для C++ лучшим решением будет создание собственного mallocator, стандартного решения, основанного на функции malloc() языка C.Проверять этот, или этот.
Используйте предложенный подход — удерживайте указатель на предыдущий буфер до тех пор, пока функция realloc не вернется успешно.Как только функция realloc() успешно вернет предыдущий блок, он будет освобожден и все указатели на него станут висеть — откорректируйте их.
Realloc, как и malloc, не имеет значения, какой тип указателя — вы можете использовать void*, а также что угодно*.
Как уже говорили другие, просто используйте realloc правильно, как предложено.
Но «способ C++» сделать это на самом деле заключается в использовании std::vector<> вместо того, чтобы поддерживать массивы самостоятельно.Таким образом, стандартная библиотека C++ позаботится о низкоуровневых деталях перераспределения (предположительно, с помощью realloc()).
Когда функция realloc() терпит неудачу и возвращает NULL, исходная память остается нетронутой.
Поэтому вы должны использовать его следующим образом:
my_Struct* strPtr =(my_struct*)malloc(sizeof(my_Struct));
/* an later */
my_Struct* tmp = (my_struct*)realloc(strPtr,sizeof(my_Struct)*NBR);
if (tmp != NULL)
{
strPtr = tmp;
}
else
{
/* realloc Failed. Need to do something */
}
Почему вы используете malloc и realloc?В C++ почти всегда есть лучший способ.
Если вы используете его для создания массивов переменной длины, вам почти наверняка лучше использовать std::vector<> или, возможно, один из других шаблонов контейнеров.
Если вместо этого вы используете C, возможно, с компилятором, поддерживающим C++, то правильным способом будет второй метод, который не теряет весь блок памяти, когда его не удается выделить.
Ответ на ваш второй вопрос также зависит от того, используете ли вы C или C++.В C void * — это универсальный тип указателя данных, который можно свободно конвертировать.В C++ void * необходимо явно преобразовать.Если вы на самом деле пишете на C, вам нужно использовать malloc() и другие методы, которые работают с void *.Если вы действительно пишете на C++, вам нужно выполнить приведение типов, что усложняет задачу.Ни в одном случае функция realloc() не работает с указателями на структуру, а скорее с указателями на void.