Энциклопедия Turbo Pascal. Главы 9-11 - Проблема указателей

ОГЛАВЛЕНИЕ

Проблема указателей

Наиболее часто ошибки в Турбо Паскале связаны с неправильным употреблением указателей. Проблемы указателей делятся на две основные категории: недоразумения с действиями над указателями и случайное применение недопустимых указателей. Для разрешения проблем первого типа вы должны разобраться с указателями в языке Паскаль; для разрешения проблем второго типа вы должны всегда проверять допустимость указателей перед их применением.

Следующая программа иллюстрирует типичную ошибку с указателем, которую допустил программист:

    program WRONL; {данная программа имеет ошибку}

    type
      pntr = ^obiect;

      obiect = record
       x: char;
       y: integer;
       name:string[80];
      end;

    var
      p: pntr;

    begin
      p^.name := 'tom';
      p^.x := 'g';
      p^.y := 100;
    end.

Данная программа может аварийно завершиться, так как указатель р не принимает значение, используя New. Указатель р содержит неизвестное произвольное число, которое может указывать куда угодно в памяти компьютера. Это совсем не то, что вы хотели. Для исправления этой программы вы должны добавить строку

    New(p);

до первого использования р.

"Дикий" указатель крайне трудно выследить. Если вы осуществляете присваивание указателю значение переменной, которая не содержит недопустимый адрес, ваша программа некоторое время может работать правильно, а крах наступит после. Статистически, чем меньше ваша программа, тем больше вероятность того, что она будет работать правильно даже со сбившимся указателем, так как используется меньше памяти. По мере роста вашей програмы ошибка становится более вероятной.

Во-вторых, наиболее коварные проблемы могут возникнуть, когда используются указатели: вы можете выйти за пределы памяти в течение вызова New во время выполнения. Это вызывает ошибку во время выполнения и оно прекращается. К счастью в Турбо Паскале есть специальная встроенная функция MemAvail так, что вы можете избежать этих проблем.  MemAvail возвращает число свободных байт слева от неупорядоченного массива. В версиях, предшествующих 4.0, MemAvail  возвращает число параграфов свободной памяти. Следовательно, чтобы сделать программу полностью правильной, проверяйте наличие свободной памяти перед ее выполнением. Чтобы сделать это, вы должны знать число байт, необходимое для каждого типа данных, которые вы размещаете. Однако, это число может изменяться в зависимости от процессора и операционной системы, поэтому используйте функцию  SizeOf, которая возвращает число байт, требующихся для переменной. Измененная программа выглядит следующим образом:

     program RIOHL; {это верная программа}

     type
       pntr = ^object;

       object = record
        x: char;
        y: integer;
        name:string[80];
       end;

     var
       p: pntr;

     begin
       if MaxAvail>=SizeOf(object) then
       begin  {свободная память}
        New(p);
        p^.name := 'tom';
        p^.x := 'g';
        p^y := 100;

       end;
     end.

Одним из указаний на проблему с указателем является то, что ошибка ведет к неустойчивости в поведении. Ваша программа может работать один раз правильно, а другой раз неправильно. Иногда другие переменные будут содержать мусор без видимых причин. Если такое происходит, проверьте ваши указатели.

Хотя указатели являются вещью хлопотной, они также являются одним из самых мощных и полезных аспектов языка Паскаль. Приложите усилия заранее, чтобы научиться правильно ими пользоваться.