Проблема в том, что переменная dLocalVariable объявлена внутри функции child( ). Следовательно, в момент возврата адреса dLocalVariable из child( ) самой переменной уже не существует и адрес ссылается на память, которая вполне может быть занята для каких-то других целей.
«Ошибки подобного типа встречаются довольно часто, а способы их появления весьма разнообразны. К сожалению, такой тип ошибки пропускается компилятором и зачастую не вызывает аварийной остановки программы. Программа может отлично работать большую часть времени, пока память, которая в прошлом выделялась под dLocalVariable, не будет выделена другой переменной. Труднее всего найти ошибки, проявляющиеся спонтанно.»
[Атас!]
Использование блока памяти...115
Ошибки области видимости возникают потому, что С++ освобождает выделенную для локальных переменных память автоматически. Для решения этой проблемы необходим блок памяти, контролируемый непосредственно программистом. В этом блоке можно выделять память под переменные и удалять их независимо от того, что по этому поводу "думает" С++. Такой блок памяти называется кучей ( heap ).
Память в куче можно выделить, используя оператор new ; он пишется вместе с типом объекта, под который нужно выделить память. Приведённый ниже пример выделяет из кучи память для переменной типа double.
double* child( void )
{
double* pdLocalVariable = new double ;
return pdLocalVariable ;
}
Теперь, несмотря на то что переменная pdLocalVariable имеет область видимости в пределах функции child( ), память, на которую указывает эта переменная, не будет освобождена после выполнения функции. Выделение и освобождение памяти в куче осуществляется только явно. Освобождение памяти в куче выполняется с помощью команды delete.
void parent( void )
{
/* функция child( ) возвращает адрес переменной в куче */
double* pdMyDouble = child( ) ;
/* сохранение значения в созданной переменной */
*pdMyDouble = 1.1 ;
// ...
/* возврат памяти куче */
delete pdMyDouble ;
pdMyDouble = 0 ;
// ...
}
_________________
115 стр. Глава 8. Первое знакомство с указателями в С++
В этой программе указатель, возвращённый функцией child( ), используется для записи значения типа double в память, выделенную в куче. После того как функция выполнила все необходимые действия с этой памятью, она освобождается, а указатель pdMyDouble устанавливается равным нулю. Обнуление указателя не обязательно, но крайне желательно. В этом случае, если программист ошибётся и попытается опять записать что-либо по адресу, на который указывает pdMyDouble, произойдёт аварийный останов программы.
«Ошибку, в результате которой происходит аварийный останов программы, найти гораздо проще, чем проявляющуюся спонтанно.»
[Советы]
_________________
116 стр. Часть 2. Становимся функциональными программистами
Глава 9. ВТОРОЕ ЗНАКОМСТВО С УКАЗАТЕЛЯМИ...117ОГЛАВЛЕНИЕ
В этой главе...
►Операции с указателями 117
►Объявление и использование массивов указателей 124
Язык С++ позволяет работать с указателями так, как если бы они были переменными простых типов. ( Концепция указателей изложена в главе 8, "Первое знакомство с указателями в С++". ) Однако операции над указателями требуют знания некоторых тонкостей; именно они и рассматриваются в этой главе.
►Операции с указателями...117
Некоторые из операций, описанных в главе 3, "Выполнение математических операций", могут быть применены и к указателям. В этом разделе рассматривается использование арифметических операций при работе с указателями и массивами ( с массивами вы познакомились в главе 7, "Хранение последовательностей в массивах" ). В табл. 9.1 приведены базовые операции над указателями.
Таблица 9.1. Три операции над указателями