На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Название темы должно быть информативным !
Прежде чем задать вопрос, воспользуйтесь Поиском. и проверьте в FAQ (ЧАВО) Паскаля
Чтобы получить вразумительный ответ, подробно опишите проблему: что надо сделать, что не получается и номер ошибки (если есть), которую выводит компилятор.
Для вставки кода ваших программ используйте, пожалуйста, кнопку СODE=pas или выпадающий список СODE для других языков (подсветка синтаксиса).
[!] Как правильно задавать вопросы | Руководство по языку B.Pascal 7 & Objects/LR | Borland Pascal. Руководство пользователя
Модераторы: volvo877
  
> Ошибка "Stack overflow"
    Что значит эта 202 ошибка "Stack overflow"?
    Я никак не могу понять, написал процедуру и вставил в программу, отдельно это процедура как программа работает, но не хочет работать как процедура в другой программе. Выдает ошибку 202. Вчера что-то помучился она работала, седня опять не работает.
    Выкладываю саму процедуру. Её задача открывать уже существующий файл нетекстовой, а двоичный, считывать данные и их сортировать и снова записывать в этот же файл. Доичный файл типа сисок.
    Вот типы чтобы легче было разобраться в конструкции.
    {type
    RecBook = record
    name:string[20];
    phone:string[10];
    end;
    tipfile = file of RecBook;}

    Сама процедура:
    ExpandedWrap disabled
      Procedure Sort (var bookfile:tipfile);
       var
        work:recbook;
        i,j:integer;
        tmps:string[20];
        a,b:array[1..100] of string;
       begin
        Name_File; {еще одна процедура, я ее внизу написал}
        assign(bookfile, name);
        reset(bookfile);
         for i:=0 to filesize(bookfile)-1 do
           begin
            read(bookfile,work);
            a[i]:=work.vardas;
            b[i]:=work.phone;
          end;
            for i:=0 to filesize(bookfile)-2 do
             for j:=i+1 to filesize(bookfile)-1 do
               begin
                if a[i] > a[j] then
                  begin
                   tmps:=a[i];
                   a[i]:=a[j];
                   a[j]:=tmps;
                   tmps:=b[i];
                   b[i]:=b[j];
                   b[j]:=tmps;
                  end;
               end;
      close(bookfile);
      reset(bookfile);
       for i:=0 to filesize(bookfile)-1 do
        with work do
           begin
                vardas:=a[i];
                phone:=b[i];
                write(bookfile,work);
           end;
      close(bookfile);
      end;


    Процедура File_Name:
    ExpandedWrap disabled
      Procedure Name_File;
       begin
            write('Vvedite imia faila dannih telefonnogo spravo4nika > ');
            readln(name);
       end;

    Зарание спасибо.
      #MadCat#,
      как вызываешь Sort, покажи... А лучше - приаттачь всю программу ;)

      Цитата #MadCat# @
      Что значит эта 202 ошибка "Stack overflow"?

      Цитата
      Эта ошибка генерируется на входе в процедуру или функцию, скомпилированную в режиме {$S+} в случае, если нет достаточной области памяти для размещения локальных переменных подпрограммы...

      Так что если с вызовом все в порядке - придется играть с директивой {$M a, b, c} Конкретнее - с первым параметром, определяющим размер стека. Можно, конечно, просто отключить контроль переполнения стека через {$S-}, но это как раз крайне нежелательно делать...

      Добавлено
      Кстати, можно попробовать сделать так:
      ExpandedWrap disabled
        Procedure Sort (var bookfile:tipfile);
        var
        ...
          a, b:array[1..100] of string[20]; { <--- 20 вместо 255 !!! }

      Тогда в стеке будет заниматься гораздо меньший объем, а тебе строка длиннее 20 символов и не нужна...
        Цитата volvo877 @
        Добавлено
        Кстати, можно попробовать сделать так:
        ExpandedWrap disabled
          Procedure Sort (var bookfile:tipfile);
          var
          ...
            a, b:array[1..100] of string[20]; { <--- 20 вместо 255 !!! }

        Тогда в стеке будет заниматься гораздо меньший объем, а тебе строка длиннее 20 символов и не нужна...

        Во, точно, ты прав. Все теперь работает, спасибо. Ну, почему все-таки происходило переполнение, я несовсем понял?
          Я так понимаю, что стеки здесь не используются. Остаётся вариант - бесконечная рекурсия в программе (процедура вызвывает саму себя беск. кол-во раз).
            Цитата Romtek @
            Я так понимаю, что стеки здесь не используются.
            Это как "не используются" ? А где же локальные переменные хранятся?

            #MadCat#, массивы
            ExpandedWrap disabled
              a, b:array[1..100] of string;

            занимают в стеке 2 * 100 * 255 байт... Это больше 50Кб. Стек по умолчанию устанавливается в 16384 байта. Так что одно из двух: либо уменьшать размер локальных переменных (что и было сделано), либо увеличивать размер стека...
              Цитата Romtek @
              Romtek, все проще
              Это первое, что мне пришло в голову, т.к. и никогда не использую стек и когда у меня такая ошибка, значит я случайно вызвал процедуру внутри самой себя...

              Добавлено
              Цитата volvo877 @
              Это как "не используются" ? А где же локальные переменные хранятся?
              Это я знаю. Я имел в виду саму структуру данных типа стек.
                volvo877 тут что-то с выводом теперь нето.
                У тебе паскаль имеется? Если да попробуй запустить этот код.
                Я тут выкладываю его без поиска, изменения записи, дополнения они работают.
                Попробуй создать файл внести туда имя и телефон, а потом отсортировать и просмотреть его, там какая-то белеберда с выводом первой и второй записи телефонов.
                ExpandedWrap disabled
                  Program Book;
                  uses crt;
                   
                  Type
                      RecBook = Record
                       vardas: string[20];
                       phone: string[10];
                      End;
                      tipfile = file Of RecBook;
                   
                  Var
                    bookfile: tipfile;
                    work: RecBook;
                    vid: byte;
                    End_Menu: boolean;
                    name: string[12];
                   
                  Procedure Name_File;
                   Begin
                        write('Введите имя файла данных телефонного справочника > ');
                        readln(name);
                   End;
                   
                  Procedure Sort (Var bookfile:tipfile);
                   
                   Var
                     i,j: integer;
                     tmps: string[20];
                     a,b: array[1..100] Of string[20];
                   Begin
                     Name_File;
                     assign(bookfile, name);
                     reset(bookfile);
                     For i:=0 To filesize(bookfile)-1 Do
                       Begin
                         read(bookfile,work);
                         a[i] := work.vardas;
                         b[i] := work.phone;
                       End;
                        For i:=0 To filesize(bookfile)-2 Do
                          For j:=i+1 To filesize(bookfile)-1 Do
                            Begin
                              If a[i] > a[j] Then
                                Begin
                                  tmps := a[i];
                                  a[i] := a[j];
                                  a[j] := tmps;
                                  tmps := b[i];
                                  b[i] := b[j];
                                  b[j] := tmps;
                                End;
                            End;
                     close(bookfile);
                     reset(bookfile);
                     For i:=0 To filesize(bookfile)-1 Do
                       With work Do
                         Begin
                            vardas := a[i];
                            phone := b[i];
                            write(bookfile,work);
                         End;
                     close(bookfile);
                  End;
                   
                  Procedure Create_book_Phone;
                   
                   Var Ind,Count: integer;
                   Begin
                     Name_File;
                     Assign(Bookfile,name);
                     Rewrite(Bookfile);
                     writeln('Создание записей файла ', name);
                     write('Введите число записей в справочнике ');
                     readln(count);
                     For Ind:=1 To count Do
                        Addrec;
                     writeln('Создание файла данных телефонного справочника завершено');
                     writeln('Файл данных имеет ',Filesize(bookfile),' записи');
                     close(bookfile);
                   End;
                   
                  Procedure Outputrec;
                   Begin
                     read(bookfile,work);
                     With work Do
                       Begin
                         write('Запись No ', Filepos(bookfile),' : ');
                         writeln('ФИО: ',vardas,' телефон: ',phone);
                       End;
                    End;
                   
                  Procedure OutputAllrec;
                   Begin
                     Name_file;
                     Assign(bookfile,name);
                    {$I-}
                     Reset(bookfile);
                    {$I+}
                     If IOresult = 0 Then
                       Begin
                         seek(bookfile, 0);
                         writeln('*** Вывод телефонного справочника из файла ',name,'***');
                         while not Eof(bookfile) Do
                         Outputrec;
                       End
                     Else
                       writeln('Файла с именем ',name,' на диске нет');
                   End;
                   
                  Begin
                    Clrscr;
                    End_menu := false;
                    Repeat
                      writeln('*** Телефонный справочник ***');
                      writeln(' Выберите вид работы: ');
                      writeln(' 1 - создание нового файла');
                      writeln(' 2 - просмотр');
                      writeln(' 3 - изменение записи');
                      writeln(' 4 - дополнение');
                      writeln(' 5 - сортировка');
                      writeln(' 6 - поиск');
                      writeln(' 0 - exit');
                      write('Ваш выбор ');
                      readln(vid);
                      Case vid Of
                        1:  Create_book_phone;
                        2:  Outputallrec;
                        3:  Updaterec;
                        4:  Addrectoend;
                        5:  sort(bookfile);
                        6:  search_pavarde;
                        0:  end_menu := true;
                      End;
                      writeln('для продолжения нажмите Enter');
                      readln;
                      clrscr;
                    Until end_menu;
                   End.
                  Файл не компилируется - неполная версия.
                  Что значит "белибрда" ?

                  Добавлено
                  Почему work описана как глобальная переменная, а ты вводишь её ещё как локальную в Sort ?
                  Сообщение отредактировано: Romtek -
                    #MadCat#,
                    я тебе и без компиляции скажу, где проблема:
                    ExpandedWrap disabled
                      Procedure Sort (var bookfile:tipfile);
                      var
                      ...
                        a,b:array[1..100] of string[20];
                      begin
                      ...
                        for i:=0 to filesize(bookfile)-1 do begin
                          read(bookfile,work);
                          a[i]:=work.vardas; { <--- Вот тут проблема }
                          b[i]:=work.phone;
                        end;

                    Ты же обращаешься к нулевому элементу, а он не определен...
                    Если уж на то пошло, то я бы делал немного иначе (использовал бы счетчик, и при сортировке не привязывался к размеру файла, не нужно это никому...) :
                    ExpandedWrap disabled
                      var count: integer;
                      ...
                      count := 0;
                      while not eof(bookfile) do begin
                        read(bookfile,work); inc(count);
                        a[count]:=work.vardas;
                        b[count]:=work.phone;
                      end;
                      for i:=1 to pred(count) do
                        for j:=i+1 to count do begin
                          ...
                        end;
                      Цитата Romtek @
                      Файл не компилируется - неполная версия.
                      Что значит "белибрда" ?

                      Добавлено
                      Почему work описана как глобальная переменная, а ты вводишь её ещё как локальную в Sort ?

                      Белиберда - это я имел ввиду, что там пишет какие-то неясные символы.

                      А кто мне мешает переменную Work использовать в процедуре? Ну и что, что она глобальная, она как вспомогательная идет и в разных процедурах принимает разные значения типа списка.
                      Цитата

                      Если уж на то пошло, то я бы делал немного иначе (использовал бы счетчик, и при сортировке не привязывался к размеру файла, не нужно это никому...) :

                      Да этот способ куда лучше, теперь нормально, т.е. теперь я могу не задавать в масиве String[20]? Можно просто, как String и переполнений не будет?

                      Добавлено
                      А, нет ругается все все-таки надо задавать ограничение.
                        Цитата #MadCat# @
                        Можно просто, как String и переполнений не будет?

                        :no: Не меняй на String... Опять получишь "Stack Overflow", у тебя же опять размер локальных переменных увеличится...

                        А хочешь еще одно улучшение? Смотри:
                        ExpandedWrap disabled
                          Procedure Sort (Var bookfile:tipfile);
                          Var
                            tmps: RecBook;
                            arr: array[1..100] Of RecBook;
                          Begin
                            ...
                            Count := 0;
                            While not Eof(bookfile) Do Begin
                              Inc(count);
                              Read(bookFile, arr[count]);
                            End;
                           
                            for i:=1 to pred(count) do
                              for j:=i+1 to count do begin
                                if arr[i].vardas > arr[j].vardas then begin
                                  tmps := arr[i]; arr[i] := arr[j]; arr[j] := tmps;
                                end;
                           
                            reset(bookfile);
                            For i:=1 To count do
                              write(bookfile, arr[i]);
                            ...
                          Цитата #MadCat#
                          ExpandedWrap disabled
                               close(bookfile);
                               reset(bookfile);
                               For i:=0 To filesize(bookfile)-1 Do
                                 With work Do
                                   Begin
                                      vardas := a[i];
                                      phone := b[i];
                                      write(bookfile,work);
                                   End;
                               close(bookfile);
                          Ты сначала закрываешь файл, потом снова открываешь. Зачем?
                          Можно просто установить указатель файла на нулевую запись (начало) с помошью Seek (bookfile, 0);
                          Тогда
                          ExpandedWrap disabled
                               close(bookfile);
                               reset(bookfile);
                          можно удалить.

                          Добавлено
                          Цитата #MadCat# @
                          А кто мне мешает переменную Work использовать в процедуре? Ну и что, что она глобальная, она как вспомогательная идет и в разных процедурах принимает разные значения типа списка.
                          Чтобы по ошибке не подумать, что она имеет то же значение, что и в глобальной переменной.

                          Кстати, значения полей записи не нужно менять, т.к. ТП7 допускает присвоение записи значения другой записи, т.е.
                          ExpandedWrap disabled
                            temp := work1;
                            work1 := work2;
                            work2 := temp;
                            Цитата volvo877 @
                            Цитата #MadCat# @
                            Можно просто, как String и переполнений не будет?

                            :no: Не меняй на String... Опять получишь "Stack Overflow", у тебя же опять размер локальных переменных увеличится...

                            А хочешь еще одно улучшение? Смотри:
                            ExpandedWrap disabled
                              Procedure Sort (Var bookfile:tipfile);
                              Var
                                tmps: RecBook;
                                arr: array[1..100] Of RecBook;
                              Begin
                                ...
                                Count := 0;
                                While not Eof(bookfile) Do Begin
                                  Inc(count);
                                  Read(bookFile, arr[count]);
                                End;
                               
                                for i:=1 to pred(count) do
                                  for j:=i+1 to count do begin
                                    if arr[i].vardas > arr[j].vardas then begin
                                      tmps := arr[i]; arr[i] := arr[j]; arr[j] := tmps;
                                    end;
                               
                                reset(bookfile);
                                For i:=1 To count do
                                  write(bookfile, arr[i]);
                                ...

                            А понятно всё. Тоже вариант неплохой.
                            Цитата

                            Ты сначала закрываешь файл, потом снова открываешь. Зачем?
                            Можно просто установить указатель файла на нулевую запись (начало) с помошью Seek (bookfile, 0);

                            Точно.Попробую.
                              Цитата volvo877 @

                              #MadCat#, массивы
                              ExpandedWrap disabled
                                a, b:array[1..100] of string;

                              занимают в стеке 2 * 100 * 255 байт... Это больше 50Кб.

                              2*100*255=51000 байт, а 51000/1024=49,8kb... < 50kb
                                Смысл от этого не изменился. Это все равно больше значения по умолчанию.
                                  Цитата #MadCat# @
                                  2*100*255=51000 байт, а 51000/1024=49,8kb... < 50kb

                                  Цитата volvo877 @
                                  Смысл от этого не изменился. Это все равно больше значения по умолчанию.
                                  А по-моему ошибка не из-за этого.
                                  ExpandedWrap disabled
                                    var
                                       a, b: array[1..100] of string;
                                       s: string;
                                       i: byte;
                                     
                                    begin
                                         s := '';
                                         for i := 1 to 255 do
                                             s := s + chr(i);
                                     
                                         for i := 1 to 100 do
                                             a[i] := s;
                                     
                                         a := b;
                                    end.
                                  Почему тогда здесь такой ошибки не возникает?
                                    Цитата Romtek @
                                    Почему тогда здесь такой ошибки не возникает?

                                    здесь a и b - глобальные переменные, следовательно размещаются они в сегменте данных, а не в стеке... А размер DS = 64К. Но попробуй сделать так:
                                    ExpandedWrap disabled
                                      var
                                         a, b, c: array[1..100] of string;
                                      ...

                                    Что будет? Сегмент данных переполняется и ... "Too many variables" :whistle: В случае же локальных переменных - переполняется стек. Кстати, попробуй в исходной программе добавить {$M 65520, 0, 0} и переполнения уже не будет.
                                      Я пробовал также и с локальными переменными в процедуре, и тоже не было проблем (только если не больше двух переменных).
                                      В программе Ash только 2 переменные.
                                        Ты хочешь сказать, что вот это:
                                        ExpandedWrap disabled
                                          procedure test;
                                          var
                                            a, b: array[1..100] of string;
                                            s: string;
                                            i: byte;
                                           
                                          begin
                                            s := '';
                                            for i := 1 to 255 do
                                              s := s + chr(i);
                                           
                                            for i := 1 to 100 do
                                              a[i] := s;
                                           
                                            a := b;
                                          end;
                                           
                                          begin
                                            test;
                                          end.

                                        у тебя компилируется и отрабатывает без ошибок? :wacko: В Турбо-Паскале? У меня при входе в процедуру - "Stack Overflow". Может в FPC это и сработает, но в TP - нет... Кстати, возможно дело в этом: зайди в "Options -> Memory Sizes" и посмотри установленный по умолчанию размер стека. Может ты его переустанавливал. У меня он равен 16384...
                                          Цитата volvo877 @
                                          Ты хочешь сказать, что вот это:
                                          ExpandedWrap disabled
                                            procedure test;
                                            var
                                              a, b: array[1..100] of string;
                                              s: string;
                                              i: byte;
                                             
                                            begin
                                              s := '';
                                              for i := 1 to 255 do
                                                s := s + chr(i);
                                             
                                              for i := 1 to 100 do
                                                a[i] := s;
                                             
                                              a := b;
                                            end;
                                             
                                            begin
                                              test;
                                            end.

                                          у тебя компилируется и отрабатывает без ошибок? :wacko: В Турбо-Паскале?
                                          :yes:
                                          В настройках ничего не менял, стоит 16384 :unsure:
                                            "Options -> Compiler -> Stack Checking" включен? При выключенном и у меня работает, но ... Сам понимаешь, чем это может кончиться ;)
                                              Цитата volvo877 @
                                              "Options -> Compiler -> Stack Checking" включен?
                                              ...выключен.

                                              Цитата volvo877 @
                                              ам понимаешь, чем это может кончиться
                                              Buffer Overflow? :D
                                                Цитата Romtek @
                                                Buffer Overflow? :D

                                                А попробуй запустить вот эту (правильную) программу:
                                                ExpandedWrap disabled
                                                  {$m 60000, 0, 0}
                                                  procedure test;
                                                  var
                                                    a, b: array[1..100] of string;
                                                    s: string;
                                                    i, count: byte;
                                                   
                                                  begin
                                                    s := '';
                                                    for i := 1 to 255 do
                                                      s := s + chr(i);
                                                   
                                                    for i := 1 to 100 do
                                                      a[i] := s;
                                                   
                                                    for i := 1 to 100 do
                                                      if a[1] <> a[i] then inc(count);
                                                    writeln(count);
                                                   
                                                    a := b;
                                                  end;
                                                   
                                                  begin
                                                    test;
                                                  end.

                                                и свою:
                                                ExpandedWrap disabled
                                                  procedure test;
                                                  var
                                                    a, b: array[1..100] of string;
                                                    s: string;
                                                    i, count: byte;
                                                   
                                                  begin
                                                    s := '';
                                                    for i := 1 to 255 do
                                                      s := s + chr(i);
                                                   
                                                    for i := 1 to 100 do
                                                      a[i] := s;
                                                   
                                                    for i := 1 to 100 do
                                                      if a[1] <> a[i] then inc(count);
                                                    writeln(count);
                                                   
                                                    a := b;
                                                  end;
                                                   
                                                  begin
                                                    test;
                                                  end.

                                                И посмотри на результаты :blink: Чувствуешь разницу?
                                                  Без галочки:
                                                  0 - твоя (проблем нет)
                                                  0 - моя (проблем нет)

                                                  С галочкой:
                                                  0 - твоя (проблем нет)
                                                  Stack overflow error (понятное дело! Вопрос: "на что это может повлиять?")
                                                    Я не о том, что есть или нет проблемы :) Сколько она тебе печатает? У меня без директивы {$M} (и без галочки, естественно) печатает число 24, то есть 24 (!!!) несовпадения 1-го элемента с последующими, а с директивой {$M} несовпадений нет...

                                                    А сколько по-твоему НЕсовпадений должно быть?
                                                      Я же написал, печатает 0 (ноль) без галки в обеих программах. Проверял 5 раз: то есть никаких отклонений не было найдено.

                                                      Цитата volvo877 @
                                                      А сколько по-твоему НЕсовпадений должно быть?
                                                      Наверно зависит от того, насколько переполнен стек...не хочу гадать.

                                                      Добавлено
                                                      Я считаю, что проверки компилятора нужны только на этапе отладки программы, а в релизе программист должен учесть все варианты.
                                                      0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                      0 пользователей:


                                                      Рейтинг@Mail.ru
                                                      [ Script execution time: 0.1350 ]   [ 15 queries used ]   [ Generated: 4.05.26, 07:43 GMT ]