Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как найти ошибку? / 25 сообщений из 30, страница 1 из 2
19.09.2018, 13:02
    #39704874
Валерий666
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Вобщем не могу понять что и откуда берется. После окончания события вылазит "Invalid pointer operation" или вовсе крэш памяти.
Все отрабатывает, отладчик все проглатывает, потреково все отлично, нигде не вылазят исключения, нет пустых данных, предпросмотр отчета отображается. После закрытия окна предпросмотра - ошибка. Думал дело в файле отчета, проверил, даже файл подменил другим. Ситуация не поменялась.
Вот код обработчика:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
procedure TForm8.sBitBtn1Click(Sender: TObject);
var m: TfrxRichView;
theme_array: array of integer;
tmp_array: array of string;
i:integer;
all: array of integer;
begin
 // Получаем список номенклатуры из справочника
  GetInfoRepSQL('SELECT * FROM kodvopr WHERE (torep=1) ORDER BY KOD11');
  //Определяем размер массивов
  SetLength(tmp_array, Form1.ZReport.RecordCount);
  SetLength(theme_array, Form1.ZReport.RecordCount);
  SetLength(all, 5);
  Form1.ZReport.First;
    while not Form1.ZReport.Eof do
      begin     // записываем в массив циферные обозначения номенклатуры
        tmp_array[Form1.ZReport.RecNo-1]:=Form1.ZReport.FieldByName('KODnom').AsString;
        Form1.ZReport.Next;
      end;

// По циклу из массива номенклатуры, делаем запросы по базе обращений
  for i:=0 to length(tmp_array)-1 do
    begin
        GetInfoRepSQL('SELECT themeid FROM register WHERE themeid=('''+tmp_array[i]+''')');
        theme_array[i]:=Form1.ZReport.RecordCount;
        all[0]:=all[0]+Form1.ZReport.RecordCount; // общее количество
    end;
  all[1]:=theme_array[0]+theme_array[1]+theme_array[2]+theme_array[3]+theme_array[4]+theme_array[5]+theme_array[6]+theme_array[7]+theme_array[8]+theme_array[9]+theme_array[10];
  all[2]:=theme_array[7]+theme_array[8];
  all[3]:=theme_array[11]+theme_array[12]+theme_array[13];
  all[4]:=theme_array[17]+theme_array[18]+theme_array[19];
  all[5]:=theme_array[20]+theme_array[21]+theme_array[22]+theme_array[23]+theme_array[24]+theme_array[25]+theme_array[26]+theme_array[27];

  Form1.frxReport1.LoadFromFile(Form1.sPath + '\reports\' + 'theme.fr3', true);

// Заполняем данными отчет
with Form1.frxReport1.Variables do
     begin
        Variables[' ' + 'MyDefaultCategory'] := Null;  //Создаем пустую категорию для дальнейшего создания переменных в отчете
        Variables['period'] := quotedstr(sDateEdit1.Text+' - '+sDateEdit2.Text);

            for i:=1 to length(theme_array) do
            begin     // заполняем переменные отчета
                     Variables['t'+inttostr(i)] := quotedstr(inttostr(theme_array[i]));
            end;

            for i:=0 to 5 do
            begin     // заполняем результирующие переменные отчета
              Variables['all'+inttostr(i)] := quotedstr(inttostr(all[i]));
            end;

      end;
  frxReport1.ShowReport(true);
end;


Куда копать?
...
Рейтинг: 0 / 0
19.09.2018, 13:04
    #39704878
asviridenkov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Валерий666,

all[5]
...
Рейтинг: 0 / 0
19.09.2018, 13:04
    #39704879
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Валерий666SetLength(tmp_array, Form1.ZReport.RecordCount);

У меня для тебя плохие новости: RecordCount не всегда возвращает реальное количество
записей в Dataset-е.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.09.2018, 13:07
    #39704882
goldmi45
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Валерий666
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
procedure TForm8.sBitBtn1Click(Sender: TObject);
var m: TfrxRichView;
theme_array: array of integer;
tmp_array: array of string;
i:integer;
all: array of integer;
begin
 // Получаем список номенклатуры из справочника
  GetInfoRepSQL('SELECT * FROM kodvopr WHERE (torep=1) ORDER BY KOD11');
  //Определяем размер массивов
  SetLength(tmp_array, Form1.ZReport.RecordCount);
  SetLength(theme_array, Form1.ZReport.RecordCount);
  SetLength(all, 5); // от 0 до 4
  Form1.ZReport.First;
    while not Form1.ZReport.Eof do
      begin     // записываем в массив циферные обозначения номенклатуры
        tmp_array[Form1.ZReport.RecNo-1]:=Form1.ZReport.FieldByName('KODnom').AsString;
        Form1.ZReport.Next;
      end;

// По циклу из массива номенклатуры, делаем запросы по базе обращений
  for i:=0 to length(tmp_array)-1 do
    begin
        GetInfoRepSQL('SELECT themeid FROM register WHERE themeid=('''+tmp_array[i]+''')');
        theme_array[i]:=Form1.ZReport.RecordCount;
        all[0]:=all[0]+Form1.ZReport.RecordCount; // общее количество
    end;
  all[1]:=theme_array[0]+theme_array[1]+theme_array[2]+theme_array[3]+theme_array[4]+theme_array[5]+theme_array[6]+theme_array[7]+theme_array[8]+theme_array[9]+theme_array[10];
  all[2]:=theme_array[7]+theme_array[8];
  all[3]:=theme_array[11]+theme_array[12]+theme_array[13];
  all[4]:=theme_array[17]+theme_array[18]+theme_array[19];
  all[5]:=theme_array[20]+theme_array[21]+theme_array[22]+theme_array[23]+theme_array[24]+theme_array[25]+theme_array[26]+theme_array[27]; //а это куда?

  Form1.frxReport1.LoadFromFile(Form1.sPath + '\reports\' + 'theme.fr3', true);

// Заполняем данными отчет
with Form1.frxReport1.Variables do
     begin
        Variables[' ' + 'MyDefaultCategory'] := Null;  //Создаем пустую категорию для дальнейшего создания переменных в отчете
        Variables['period'] := quotedstr(sDateEdit1.Text+' - '+sDateEdit2.Text);

            for i:=1 to length(theme_array) do
            begin     // заполняем переменные отчета
                     Variables['t'+inttostr(i)] := quotedstr(inttostr(theme_array[i]));
            end;

            for i:=0 to 5 do // 0,1,2,3,4,5 - итого 6
            begin     // заполняем результирующие переменные отчета
              Variables['all'+inttostr(i)] := quotedstr(inttostr(all[i]));
            end;

      end;
  frxReport1.ShowReport(true);
end;


Куда копать?
...
Рейтинг: 0 / 0
19.09.2018, 13:18
    #39704901
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Хоть и есть ошибка в непонимание выделенного массива, то что элементы с нуля.


Но, ошибка - "Invalid pointer operation" означает обращение к не выделенной памяти указателя.

А неверное обращение к элементу должно расцениваться как Range check error
...
Рейтинг: 0 / 0
19.09.2018, 13:20
    #39704904
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Информация о такой ошибки могла бы стать строка
Код: pascal
1.
        tmp_array[Form1.ZReport.RecNo-1]:=Form1.ZReport.FieldByName('KODnom').AsString;



В диалоговом окне, трудно нажать break ?
...
Рейтинг: 0 / 0
19.09.2018, 13:22
    #39704908
Любезный
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Живой пример, как не надо писать приложения. Элементы одной формы обращаются к элементам другой... Вынеси логику в отдельный от интерфейса пользователя модуль и делай все в нем. Потом ведь допиливать и поддерживать проще будет.
...
Рейтинг: 0 / 0
19.09.2018, 13:24
    #39704909
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
авторfor i:=0 to length(tmp_array)-1 do

лучше использовать Low и High
...
Рейтинг: 0 / 0
19.09.2018, 13:26
    #39704910
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
X11авторfor i:=0 to length(tmp_array)-1 do

лучше использовать Low и High
Чем лучше ?
...
Рейтинг: 0 / 0
19.09.2018, 13:38
    #39704926
asutp2
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
defecator,

при использовании Low и High границы массива нужно менять только в одном месте, ибо не все массивы начинаются с 0 ))))

простейший пример:

Array1: array[0..999] of Byte;

for I := 0 to 999 do // при изменении описания массива здесь тоже нужно менять
Array1[I] := 1;

for I := Low(Array1) to High(Array1) do // при изменении описания массива здесь ничего менять не нужно
Array1[I] := 1;

а еще вспоминаем кроссплатформенность)) Хотя кому я говорю, ты даже до древнейшей D7 не заапгрейдился)
...
Рейтинг: 0 / 0
19.09.2018, 13:40
    #39704930
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
defecatorX11пропущено...


лучше использовать Low и High
Чем лучше ?

чем от 0 до -1
...
Рейтинг: 0 / 0
19.09.2018, 13:42
    #39704935
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
А если массив начинается не 0 или даже не 1?

Var
X: array[3..10] of Integer;
...
Рейтинг: 0 / 0
19.09.2018, 13:44
    #39704938
X11
X11
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
var
 I: Byte;
 X: array[3..10] of Integer;
 Sum: Integer;
begin
 for I:= Low(X) to High(X) do X[I]:=I;
 Sum:= 0;
 for I:= Low(X) to High(X) do Sum:= Sum+ X[I];
end;



Если в объявлении массива поменять [3..10] на [5..18], например, то в объявлении цикла ничего менять не придётся
...
Рейтинг: 0 / 0
19.09.2018, 13:57
    #39704947
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
ГирлионайльдоНо, ошибка - "Invalid pointer operation" означает обращение к не выделенной памяти указателя.Нет. Она означает повреждение служебной памяти. Например префикса массива
ГирлионайльдоА неверное обращение к элементу должно расцениваться как Range check errorПри включенной проверке Range check
...
Рейтинг: 0 / 0
19.09.2018, 14:07
    #39704957
Валерий666
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
asviridenkovВалерий666,

all[5]
Спасибо! Глаз замылился...
...
Рейтинг: 0 / 0
19.09.2018, 14:09
    #39704960
Валерий666
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Dimitry SibiryakovВалерий666SetLength(tmp_array, Form1.ZReport.RecordCount);

У меня для тебя плохие новости: RecordCount не всегда возвращает реальное количество
записей в Dataset-е.

Это зависит от их количества? Скажем до 10000 я проблем таких не видел
...
Рейтинг: 0 / 0
19.09.2018, 14:17
    #39704964
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Валерий666Это зависит от их количества?

Это зависит от особенностей реализации конкретного класса.

И, кстати, ты уверен, что у тебя все запросы возвращают одинаковое количество записей?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.09.2018, 14:21
    #39704968
Валерий666
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Dimitry SibiryakovВалерий666Это зависит от их количества?

Это зависит от особенностей реализации конкретного класса.

И, кстати, ты уверен, что у тебя все запросы возвращают одинаковое количество записей?..


Имеется ввиду разные или один и то же выполненный 1000 раз?
Пока база не большая 20 записей, все проверяемо и отображается правильно.
...
Рейтинг: 0 / 0
19.09.2018, 14:41
    #39704996
Ivan_Pisarevsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Валерий666Пока база не большая 20 записей, все проверяемо и отображается правильно.Короче : "Сегодня детских не завезли". Все еще впереди.

Если датасет еще не сфетчил все записи, а транзакция ридкоммиитед, то... дальше сам или еще что-то нужно пояснять?
...
Рейтинг: 0 / 0
19.09.2018, 14:42
    #39704998
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
Валерий666Имеется ввиду разные или один и то же выполненный 1000 раз?

Мне отсюда не видно что делает процедура GetInfoRepSQL(), но я сильно подозреваю, что она
меняет содержимое Form1.ZReport и это содержимое может уже не поместиться в массив,
выделенный под старое количество RecordCount.

Валерий666Пока база не большая 20 записей, все проверяемо и отображается правильно.

20 записей? А что тогда заносится в theme_array с 20-го по 27-й номер?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
19.09.2018, 14:50
    #39705011
Любезный
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
авторА если массив начинается не 0 или даже не 1?
В этом случае Low и High не помогут. Проверял на D2010.
...
Рейтинг: 0 / 0
19.09.2018, 14:58
    #39705024
defecator
Модератор форума
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
asutp2defecator,

при использовании Low и High границы массива нужно менять только в одном месте, ибо не все массивы начинаются с 0 ))))

простейший пример:

Array1: array[0..999] of Byte;

for I := 0 to 999 do // при изменении описания массива здесь тоже нужно менять
Array1[I] := 1;

for I := Low(Array1) to High(Array1) do // при изменении описания массива здесь ничего менять не нужно
Array1[I] := 1;

а еще вспоминаем кроссплатформенность))

а ещё можно завести константы, определяющие размерность массива,
и использовать только их (как раз мой вариант)
...
Рейтинг: 0 / 0
19.09.2018, 15:32
    #39705059
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
_Vasilisk_Нет. Она означает повреждение служебной памяти. Например префикса массива


Доказательства в студию! Если бы так было, то выскочила ошибка AV подобная 'write of address 0xXXXXXXXX'
...
Рейтинг: 0 / 0
19.09.2018, 15:37
    #39705065
Гирлионайльдо
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
_Vasilisk_При включенной проверке Range check

А вот и нет. Она у меня выскакивает даже при выключенной

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
program Project2;


{$APPTYPE CONSOLE}
{$R *.res}

uses
  System.SysUtils;

var
  i, Rand: Integer;
  Arr: array of Integer;

begin
  try
    Randomize;
    while True do
    begin
      Rand := Random(i.MaxValue);
      Writeln(Rand);
      SetLength(Arr, Rand);
      for i := 0 to i.MaxValue - 1 do
        Arr[i] := i;
      Writeln(Arr[i]);
      Readln;
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;

end.

...
Рейтинг: 0 / 0
19.09.2018, 18:07
    #39705179
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Как найти ошибку?
ГирлионайльдоА вот и нет. Она у меня выскакивает даже при выключенной
Код: pascal
1.
2.
3.
4.
5.
6.
7.
procedure TForm1.FormCreate(Sender: TObject);
var
  LData: array of Integer;
begin
  SetLength(LData, 1);
  LData[1] := 2;
end;

При подключенном FastMM на выходе из процедуры FastMM ругается на поврежденный футер блока. При отсутствии FastMM на закрытие программы начинаются сыпаться произвольные ошибки.

Если добавить
Код: pascal
1.
{$R+}

то на строке
Код: pascal
1.
LData[1] := 2;

ожидаемый
---------------------------
Debugger Exception Notification
---------------------------
Project Project1.exe raised exception class ERangeError with message 'Range check error'.
---------------------------
Break Continue Help
---------------------------

ГирлионайльдоДоказательства в студию!SysUtils.pas
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
procedure ErrorHandler(ErrorCode: Byte; ErrorAddr: Pointer);
var
  E: Exception;
begin
  case ErrorCode of
    Ord(reOutOfMemory):
      E := OutOfMemory;
    Ord(reInvalidPtr):
      E := InvalidPointer;
    Ord(reDivByZero)..Ord(High(TRuntimeError)):
      E := ExceptTypes[ExceptMap[ErrorCode].EClass].Create(ExceptMap[ErrorCode].EIdent);
  else
    E := CreateInOutError;
  end;
  if ErrorAddr <> nil then
    raise E at ErrorAddr
  else
    raise E;
end;

поискать по исходникам строку reInvalidPtr - задание на дом
ГирлионайльдоЕсли бы так было, то выскочила ошибка AV подобная 'write of address 0xXXXXXXXX'Чушь! Вот именно эта ошибка обозначает обращение к невыделенной (или освобожденной) памяти
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Как найти ошибку? / 25 сообщений из 30, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]