ошибка 201 при работе с дин. масивом

Форум для изучающих FPC и их учителей.

Модератор: Модераторы

ошибка 201 при работе с дин. масивом

Сообщение anjeyka » 02.10.2009 13:10:25

доброго времени суток
есть такая проблема при работе с динамическим масивом spectr
задаю длину масива [0..2*10e6, 0..1] - ок (долго соображает)
записую данные в масив - на 100000-200000 ок
выхожу из цикла - ок
потом программа долго соображает и вылетает с кодом 201
0 0.000 mV 60216
0 0.000 mV 60217
End read Data to Buffer, go write to File
Runtime error 201 at $00002ACD
$00002ACD
$00005E9A
$00002094

при длине до 20000 все работает
FreePascal IDE for GO32 V2 DOS extender
Target CPU: i386
Version 1.0.10 2009/04/01
(Compiler Version 2.2.4)
(Debugger GDB 6.1.1)
OS: Win98

Код: Выделить всё
var   data  : array[1..5] of integer;
     digit : array[1..4] of real;
     spectr: array of array of real;
     i, vel : integer;
     velk, cnt : longint;
     value, xmax, xmin, xexit : real;
     fout : text;
     port : tport;

begin
...
xexit:=1900*(xmax-xmin)*velk;
SetLength(spectr, round(xexit), 2);

assign(fout,fname);
rewrite(fout);

cnt:=0;
while (not keypressed) and (cnt<xexit) do            {nachalo izmereniya}
begin
  ...
   spectr[cnt,0]:=1; spectr[cnt,1]:=value;
...
   inc(cnt);
end;

writeln('End read Data to Buffer, go write to File');
                                 { Error }
for i:=0 to cnt-1 do
   begin
     writeln(fout, spectr[i,0]:0:0, ' ', spectr[i,1]:5:5);
     writeln(i);
     flush(fout);
   end;
close(fout);
anjeyka
незнакомец
 
Сообщения: 6
Зарегистрирован: 02.10.2009 12:36:44
Откуда: Киев, Украина

Re: ошибка 201 при работе с дин. масивом

Сообщение Mr.Smart » 02.10.2009 14:19:26

anjeyka
Не очень понятно как вы инициализируете динамический массив.
У вас есть массив следующего вида:
Код: Выделить всё
spectr: array of array of real;

это значит, что у вашего массива каждый элемент является тоже динамическим массивом, но судя по представленному коду вы производите инициализацию только основной массив (если конечно случайно вы не вырезали код), а обращаетесь к ячейкам не инициализированных подмассивов.
Инициализация вашего массива будет примерно следующая:
Код: Выделить всё
SetLength(spectr,...);
  for j:=0 to ... do
   SetLength(spectr[j],...);
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: ошибка 201 при работе с дин. масивом

Сообщение anjeyka » 02.10.2009 14:31:46

Код: Выделить всё
spectr: array of array of real;
- двух-мерный масив
и размер задаеться стандартно:
Код: Выделить всё
SetLength(spectr, x, y);

в моем случае x - round(xexit), y - 2

оф. доки http://www.freepascal.org/docs-html/ref/refsu14.html
Код: Выделить всё
program testarray1; 

Type 
  TA = Array of array of Integer; 

var 
  A,B : TA; 
  I,J : Integer; 
begin 
  Setlength(A,10,10); 
...

anjeyka
незнакомец
 
Сообщения: 6
Зарегистрирован: 02.10.2009 12:36:44
Откуда: Киев, Украина

Re: ошибка 201 при работе с дин. масивом

Сообщение Mr.Smart » 02.10.2009 15:07:33

anjeyka писал(а):
Код: Выделить всё
SetLength(spectr, x, y);

Фига се :shock: А я всегда думал, что только один параметр :oops:
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: ошибка 201 при работе с дин. масивом

Сообщение Sergei I. Gorelkin » 02.10.2009 15:23:22

Объяви отсчет как статический массив из двух элементов:
sample = array[0..1] of real;
А потом одномерный динамический массив из них:
var spectr: array of sample;
Потом еще придется скобки по-другому расставить, вместо spectr[cnt,0] будет spectr[cnt][0].

Но при этом, во-первых, вместо 2*1e6 выделений памяти будет ровно одно, во-вторых, самой памяти потребуется как минимум вдвое меньше, в-третьих, вся математика с этими данными будет шустрее, т.к. данные лежат подряд, а не размазаны тонким слоем по всему адресному пространству.

Если и так не заработает, то это уже претензии к DPMI. Цифра 20000, вообще, наводит на мысли, что там где-то присутствует ограничение 65536 байт на сегмент...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: ошибка 201 при работе с дин. масивом

Сообщение Mr.Smart » 02.10.2009 15:35:13

anjeyka
В общем попробовал по разному объявлять данный массив. Если использовать динамический массив ошибка происходит при чистки памяти.
А вот в случае объявления статического массива размером 200000 элементов ни какой ошибки не возникает....
Код: Выделить всё
arr: array[0..200000] of array [0..1] of Real;


Добавлено спустя 48 секунд:
Sergei I. Gorelkin писал(а):Если и так не заработает, то это уже претензии к DPMI. Цифра 20000, вообще, наводит на мысли, что там где-то присутствует ограничение 65536 байт на сегмент...

Ошибка вылетает и в Win32 :wink:
Mr.Smart
долгожитель
 
Сообщения: 1796
Зарегистрирован: 29.03.2008 01:01:11
Откуда: из леса!

Re: ошибка 201 при работе с дин. масивом

Сообщение Vadim » 02.10.2009 18:23:54

Вот, написал для проверки такую программку:
Код: Выделить всё
Var
  spectr: array of array of single;
  i, j: integer;

Begin
  Randomize;
  SetLength(spectr, 2 000 000, 2);
  For i:=0 to 1 999 999 Do
    For j:=0 to 1 Do
      spectr[i,j]:=Random;
  For i:=0 to 1 999 999 Do
    For j:=0 to 1 Do
      If (i=500 000) or (i=1 000 000) or (i=1 500 000) or (i=1 999 999) Then
        WriteLn(i, ' ', j, ' ', spectr[i,j]:6:3);
  WriteLn('Это конец...');
End.

Вот её вывод:
Код: Выделить всё
500000 0  0.247
500000 1  0.174
1000000 0  0.849
1000000 1  0.137
1500000 0  0.299
1500000 1  0.243
1999999 0  0.041
1999999 1  0.154
Это конец...

Или я чего-то не понял, или проблема в другом месте.
Компилятор 2.2.5.
Последний раз редактировалось Vadim 02.10.2009 19:03:44, всего редактировалось 1 раз.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: ошибка 201 при работе с дин. масивом

Сообщение Sergei I. Gorelkin » 02.10.2009 18:33:46

У меня примерно такая же программа тоже отработала без вопросов, и на Windows XP, и на Windows 98, FPC 2.5.1.

Так что происходящее становится больше похожим на затирание памяти в каком-то другом месте...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: ошибка 201 при работе с дин. масивом

Сообщение anjeyka » 06.10.2009 12:47:20

програмка работает и у меня,
правда пришлось заменить тип "integer" на "LongInt" :?
Код: Выделить всё
_ Free Pascal IDE Version 1.0.10 [2009/04/01]
_ Compiler Version 2.2.4
_ GDB Version GDB 6.1.1
_ Using configuration files from: C:\PP\BIN\GO32V2\
Running "c:\pp\bin\go32v2\test_mem.exe "
500000 0  0.434
500000 1  0.618
1000000 0  0.036
1000000 1  0.762
1500000 0  0.982
1500000 1  0.602
1999999 0  0.020
1999999 1  0.041
Это конец...

:idea: есть идея - проверяю:
у меня i : integer, a cnt : longint
а перед ошибкой идет for i:=0 to cnt - integer не вмещает 2 000 000 (в моем случае)
сделал все - longint

Table 3.2: Predefined integer types

Type Range

Smallint -32768 .. 32767
Integer either smallint or longint
Longint -2147483648 .. 2147483647
Последний раз редактировалось anjeyka 06.10.2009 14:07:02, всего редактировалось 3 раз(а).
anjeyka
незнакомец
 
Сообщения: 6
Зарегистрирован: 02.10.2009 12:36:44
Откуда: Киев, Украина

Re: ошибка 201 при работе с дин. масивом

Сообщение Vadim » 06.10.2009 13:02:43

anjeyka
Тогда давайте попробуем сделать вот что. Вместо этого фрагмента:
Код: Выделить всё
for i:=0 to cnt-1 do
   begin
     writeln(fout, spectr[i,0]:0:0, ' ', spectr[i,1]:5:5);
     writeln(i);
     flush(fout);
   end;

Поставьте такой:
Код: Выделить всё
for i:=0 to High(spectr) do
   begin
     writeln(fout, spectr[i,0]:0:0, ' ', spectr[i,1]:5:5);
     writeln(i);
     flush(fout);
   end;

Функция High() гарантированно возмёт наибольший существующий индекс массива. Для данного применения это будет та цифра, которую Вы задаёте первой цифрой в процедуре SetLength() минус 1.

Добавлено спустя 3 минуты 16 секунд:
anjeyka писал(а):integer не вмещает 2 000 000

А вот и неправда. :) Тип Integer для 32-ух разрядного компилятора работает с диапазоном чисел от -2 147 483 648 до 2 147 483 647.
Последний раз редактировалось Vadim 06.10.2009 13:10:56, всего редактировалось 1 раз.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: ошибка 201 при работе с дин. масивом

Сообщение anjeyka » 06.10.2009 13:10:48

¦+------------------------------- test_mem2.pas -------------------------4-----+
¦¦program testmem2;
¦¦var i: integer;
¦¦begin
¦¦ for i:=0 to 2000000 do
¦¦end.

+-[_]---------- Compiling (Debug mode) ---------------
¦ Main file: c:\pp\bin\go32v2\test_mem2.pas
¦ Failed to compile...
¦ Target: GO32 V2 DOS extender
¦ Line number: 0 Total lines: 4
¦ Used memory: 298K Allocated memory: 3776K
¦ Total errors: 3 Compile time: 0.5s
¦ Compile failed
¦
+-[_]------------------------- Compiler Messages ------------------------5-[]-+
¦ test_mem2.pas(4,14) Error: range check error while evaluating constants 
¦ test_mem2.pas(5,4) Fatal: There were 1 errors compiling module, stopping _
¦ test_mem2.pas(0) Fatal: Compilation aborted _

может я что с компилятором натворил :(
anjeyka
незнакомец
 
Сообщения: 6
Зарегистрирован: 02.10.2009 12:36:44
Откуда: Киев, Украина

Re: ошибка 201 при работе с дин. масивом

Сообщение Vadim » 06.10.2009 13:14:04

anjeyka
Поставьте самой первой строкой программы:
{$mode objfpc}
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: ошибка 201 при работе с дин. масивом

Сообщение anjeyka » 06.10.2009 13:17:20

Vadim писал(а):Поставьте самой первой строкой программы:
{$mode objfpc}

работает :)
anjeyka
незнакомец
 
Сообщения: 6
Зарегистрирован: 02.10.2009 12:36:44
Откуда: Киев, Украина

Re: ошибка 201 при работе с дин. масивом

Сообщение Vadim » 06.10.2009 13:26:57

anjeyka
Видимо у Вас в конфигурационном файле (fpc.cfg) стоит режим совместимости с TurboPascal, у которого Integer - это нынешний SmallInt. Проверьте. Найдите в конфигурационном файле опцию -M (можно поискать по контексту). Скорее всего там будет -Mtp. Замените её на -Mobjfpc.
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: ошибка 201 при работе с дин. масивом

Сообщение anjeyka » 06.10.2009 13:50:15

Всем учасникам спасибо за обсуждение
Sergei I. Gorelkin и Vadim
отдельная благодарность за новые идеи :)
anjeyka
незнакомец
 
Сообщения: 6
Зарегистрирован: 02.10.2009 12:36:44
Откуда: Киев, Украина


Вернуться в Обучение Free Pascal

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11

Рейтинг@Mail.ru