|
Программирование >> Перегруженные имена функций и идентификаторы
эту функцию вызывать. В частности, многие функции, имеющие в качестве параметров указатели (на структуры или стринги, например), обычно вызываются с параметрами, равными адресам каких-то уже существующих объектов (структур или массивов). Другой распространенный пример - функция stat(). Предполагается, что функция, которую я использую, возвращает строку, но после возврата в вызывающую функцию эта строка содержит мусор Убедитесь, что правильно выделена область памяти, указатель на которую возвращает ваша функция. Функция должна возвращать указатель на статически выделенную область памяти или на буфер, передаваемый функции в качестве параметра, или на память, выделенную с помощью malloc(), но не на локальный (auto) массив. Другими словами, никогда не делайте ничего похожего на: char *f() char buf[10]; /* ... */ return buf; Приведем одну поправку (непригодную в случае, когда f() вызывается рекурсивно, или когда одновременно нужны несколько возвращаемых значений): static char buf[10]; Почему в некоторых исходных текстах значения, возвращаемые malloc(), аккуратно преобразуются в указатели на выделяемый тип памяти? До того, как стандарт ANSI/ISO ввел обобщенный тип указателя void *, эти преобразования были обычно необходимы для подавления предупреждений компилятора о приравнивании указателей разных типов. (Согласно стандарту C ANSI/ISO, такие преобразования типов указателей не требуются). Можно использовать содержимое динамически выделяемой памяти после того как она освобождена? Нет. Иногда в старых описаниях malloc() говорилось, что содержимое освобожденной памяти остается неизменным ; такого рода поспешная гарантия никогда не была универсальной и не требуется стандартом ANSI. Немногие программисты стали бы нарочно использовать содержимое освобожденной памяти, но это легко сделать нечаянно. Рассмотрите следующий (корректный) фрагмент программы, в котором освобождается память, занятая односвязным списком: struct list *listp, *nextp; for(listp = base; listp != NULL; listp = nextp) { nextp = listp->next; free((char *)listp); и подумайте, что получится, если будет использовано на первый взгляд более очевидное выражение для тела цикла: listp = listp->next без временного указателя nextp. Откуда free() знает, сколько байт освобождать? Функции malloc/free запоминают размер каждого выделяемого и возвращаемого блока, так что не нужно напоминать размер освобождаемого блока. А могу я узнать действительный размер выделяемого блока? Нет универсального ответа. Я выделяю память для структур, которые содержат указатели на другие динамически создаваемые объекты. Когда я освобождаю память, занятую структурой, должен ли я сначала освободить память, занятую подчиненным объектом? Да. В общем, необходимо сделать так, чтобы каждый указатель, возвращаемый malloc() был передан free() точно один раз (если память освобождается). В моей программе сначала с помощью malloc() выделяется память, а затем большое количество памяти освобождается с помощью free(), но количество занятой памяти (так сообщает команда операционной системы) не уменьшается Большинство реализаций malloc/free не возвращают освобожденную память операционной системе (если таковая имеется), а просто делают освобожденную память доступной для будущих вызовов malloc() в рамках того же процесса. Должен ли я освобождать выделенную память перед возвратом в операционную систему? Делать это не обязательно. Настоящая операционная система восстанавливает состояние памяти по окончании работы программы. Тем не менее, о некоторых персональных компьютерах известно, что они ненадежны при восстановлении памяти, а из стандарта ANSI/ISO можно лишь получить указание, что эти вопросы относятся к качеству реализации . Правильно ли использовать нулевой указатель в качестве первого аргумента функции realloc()? Зачем это нужно? Это разрешено стандартом ANSI C (можно также использовать realloc(...,0) дя освобождения памяти), но некоторые ранние реализации Си это не поддерживают, и мобильность в этом случае не гарантируется. Передача нулевого указателя realloc() может упростить написание самостартующего алгоритма пошагового выделения памяти. В чем разница между calloc и malloc? Получатся ли в результате применения calloc корректные значения нулевых указателей и чисел с плавающей точкой? Освобождает ли free память, выделенную calloc, или нужно использовать cfree? По существу calloc(m,n) эквивалентна: p = malloc(m * n); memset(p, 0, m * n); Заполнение нулями означает зануление всех битов, и, следовательно, не гарантирует нулевых значений для указателей и для чисел с плавающей точкой. Функция free может (и должна) использоваться для освобождения памяти, выделенной calloc. Что такое alloca и почему использование этой функции обескураживает? alloca выделяет память, которая автоматически освобождается, когда происходит возврат из функции, в которой вызывалась alloca. То есть, память, выделенная alloca, локальна по отношению к стековому кадру ии контексту данной функции. Использование alloca не может быть мобильным, реализации этой функции трудны на машинах без стека. Использование этой функции проблематично (и очевидная реализация на машинах со стеком не удается), когда возвращаемое ей значение непосредственно передается другой функции, как, например, в fgets(alloca(100), 100, stdin). По изложенным выше причинам alloca (вне зависимости от того, насколько это может быть полезно) нельзя использовать в программах, которые должны быть в высокой степени мобильны.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |