Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.10.2010, 22:53   #1
Marsel737
Форумчанин
 
Аватар для Marsel737
 
Регистрация: 09.11.2009
Сообщений: 669
По умолчанию Почему через раз вылазить ошибка I/O 103?

Всем доброго времени суток.

Никак не разберусь в чём тут пробелма, при закрытии вылазит, ошибка чтения/записи, причём вылазит через раз, ошибка на таких строках:

Seek(VFile, 0);
Seek(VFile, Random(FileSize(VFile)));

Текст ошибки:

First chance exception at $76C6B727. Exception class EInOutError with message 'I/O error 103'. Process labwork2.exe (5420)

После этой ошибки следующей вылазит на VCS.Leave;

Текст ошибки такой:

First chance exception at $76C6B727. Exception class EAccessViolation with message 'Access violation at address 004BA85F in module 'labwork2.exe'. Read of address 00000000'. Process labwork2.exe (4008)

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

Код:
unit umain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, SyncObjs, StdCtrls, ExtCtrls, Grids;

type
  TfrmMain = class(TForm)
    btnRun: TButton;
    shpBackgr: TShape;
    imgOutput: TImage;
    lblCntMin: TLabel;
    lblCntMax: TLabel;
    lblChr0: TLabel;
    lblChr255: TLabel;
    procedure btnRunClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  end;

  TRd = class(TThread)
    constructor Create(ASleep: boolean);
    procedure Execute; override;
    procedure OutputInfo;
    procedure Read;
  private
    imgFOutput: TImage;
    FThrId: integer;
  public
    property ThrId: integer read FThrId;
  end;

  TWr = class(TThread)
    procedure Execute; override;
    procedure Write;
  private
    FThrId: integer;
  public
    property ThrId: integer read FThrId;
  end;

const
  CThrCnt = 5;
  CDelay = 100;

var
  frmMain: TfrmMain;
  VFile: file;
  VLog: TextFile;
  VCS: TCriticalSection;
  VWr: array[1..CThrCnt] of TWr;
  VRd: array[1..CThrCnt] of TRd;
  VCh: array[0..255] of integer;

implementation

{$R *.dfm}

constructor TRd.Create(ASleep: boolean);
begin
  imgFOutput := nil;
  inherited
    Create(ASleep);
end;

procedure TRd.Execute;
begin
  repeat
    VCS.Enter;
      Synchronize(Read);
    VCS.Leave;
    Sleep(CDelay);
  until Terminated;
end;

procedure TRd.OutputInfo;
var
  I: byte;
begin
  imgFOutput.Canvas.FillRect(Rect(0, 0, imgFOutput.Width, imgFOutput.Height));
  for I := 0 to 255 do
  begin
    imgFOutput.Canvas.MoveTo(I, imgFOutput.Height);
    imgFOutput.Canvas.LineTo(I, imgFOutput.Height - VCh[I] * 2);
  end;
end;

procedure TRd.Read;
var
  CrCh: byte;
  I: byte;
begin
  for I := 0 to 255 do
    VCh[I] := 0;
  try
    Seek(VFile, 0);
    while not eof(VFile) do
    begin
      BlockRead(VFile, CrCh, 1);
      Inc(VCh[CrCh]);
    end;
    Writeln(VLog, TimeToStr(Time), ' | ThrId: ', IntToStr(ThrId),
      ' | Thread read file');
    OutputInfo;
  except
  end;
end;

procedure TfrmMain.btnRunClick(Sender: TObject);
var
  I: byte;
begin
  VCS := TCriticalSection.Create;
  for I := 1 to CThrCnt do
  begin
    VWr[I] := TWr.Create(false);
    VWr[I].FreeOnTerminate := true;
    VWr[I].FThrId := VWr[I].ThreadID;
    VRd[I] := TRd.Create(false);
    VRd[I].FreeOnTerminate := true;
    VRd[I].FThrId := VRd[I].ThreadID;
    VRd[I].imgFOutput := imgOutput;
    VRd[I].imgFOutput.Canvas.Pen.Color := clRed;
  end;
  btnRun.Enabled := false;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
  DoubleBuffered := true;
  AssignFile(VFile, 'testfile.txt');
  {$I-}
  Reset(VFile, 1);
  {$I+}
  if IOResult <> 0 then
    btnRun.Enabled := false;
  AssignFile(VLog, 'log.txt');
  Rewrite(VLog);
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
  CloseFile(VLog);
  CloseFile(VFile);
  if Assigned(VCS) then
  begin
    VCS.Free;
    VCS := nil;
  end;
end;

procedure TWr.Execute;
begin
  repeat
    VCS.Enter;
      Write;
    VCS.Leave;
    Sleep(CDelay);
  until Terminated;
end;

procedure TWr.Write;
var
  CrCh: byte;
  I: integer;
begin
  Randomize;
  try
    for I := 0 to Random(FileSize(VFile)) do
    begin
      CrCh := Random(255);
      Seek(VFile, Random(FileSize(VFile)));
      BlockWrite(VFile, CrCh, 1);
    end;
    Writeln(VLog, TimeToStr(Time), ' | ThrId: ', IntToStr(ThrId),
      ' | Thread modificate file');
  except
  end;
end;

end.
Вложения
Тип файла: zip Threads.zip (580.2 Кб, 10 просмотров)
Я не всегда знаю, о чем говорю, но знаю, что прав. © Мухаммед Али.
К чёрту обстоятельства. Я создаю возможности. © Брюс Ли
Marsel737 вне форума Ответить с цитированием
Старый 22.10.2010, 23:01   #2
Kotofff
Участник клуба
 
Аватар для Kotofff
 
Регистрация: 11.01.2009
Сообщений: 1,917
По умолчанию

А где открытие файла перед обращением к нему ?
Я вижу только при создании в FormCreate, обращения происходят не только там.
Эта ошибка как раз об этом.
"Заряженному танку в дуло не смотрят" @Dekmer in WoT
Kotofff вне форума Ответить с цитированием
Старый 22.10.2010, 23:03   #3
ex.cluz
Участник клуба
 
Аватар для ex.cluz
 
Регистрация: 15.01.2010
Сообщений: 1,325
По умолчанию

Нехило тут разбираться надо...
Первое предположение: может, файл уже закрыт, когда прога хочет к нему обратиться?
Отладчик по шагам пройдите, гляньте, что там происходит.
Грибы - они разные. Один тебя накормит, другой тебе кино покажет...
Редактор журнала "
[ПРОграммист]"
Yan's Home Digital Lab
ex.cluz вне форума Ответить с цитированием
Старый 22.10.2010, 23:07   #4
Marsel737
Форумчанин
 
Аватар для Marsel737
 
Регистрация: 09.11.2009
Сообщений: 669
По умолчанию

При создании я связываю файл, потом открываю его для чтения, при чтении каждый раз перемещаю текущую файловую позицию в начало файла и считываю файл, при закрытии формы соответственно закрываю файл.

А зачем мне каждый раз при чтении чтении файла его снова открывать, если я его закрываю только при закрытии формы.

И ещё раз повторяю при выполнении всё нормально, но при закрытии приложения вылазит ошибка.

UPD:

Прошолся отладчиком, уничтожении формы я уничтожаю критическую секцию:

Код:
if Assigned(VCS) then
  begin
    VCS.Free;
    VCS := nil;
  end;
При этом Execute у потока ещё выполняется, т.к. я сделал что процедура выполняется до закрытия приложения:

Код:
procedure TWr.Execute;
begin
  repeat
    VCS.Enter;
      Write;
    VCS.Leave;
    Sleep(CDelay);
  until Terminated;
end;
Поэтому сделал так и вроде ошибок нет:

Код:
procedure TWr.Execute;
begin
  repeat
    VCS.Enter;
      Write;
    VCS.Leave;
    Sleep(CDelay);
  until Terminated;
  CloseFile(VLog);
  CloseFile(VFile);
  if Assigned(VCS) then
  begin
    VCS.Free;
    VCS := nil;
  end;
end;
Но тогда этот код

Код:
  CloseFile(VLog);
  CloseFile(VFile);
  if Assigned(VCS) then
  begin
    VCS.Free;
    VCS := nil;
  end;
будет выполняться столько раз, сколько имеется потоков, потоэму возникает вопрос может можно как-то по другому сделать?

UPD:

Мудрить не стал, сделал так :

Код:
  if Assigned(VCS) then
  begin
    CloseFile(VLog);
    CloseFile(VFile);
    VCS.Free;
    VCS := nil;
  end;
Я не всегда знаю, о чем говорю, но знаю, что прав. © Мухаммед Али.
К чёрту обстоятельства. Я создаю возможности. © Брюс Ли

Последний раз редактировалось Marsel737; 22.10.2010 в 23:21.
Marsel737 вне форума Ответить с цитированием
Старый 22.10.2010, 23:33   #5
ex.cluz
Участник клуба
 
Аватар для ex.cluz
 
Регистрация: 15.01.2010
Сообщений: 1,325
По умолчанию

Рад, что проблема решилась. У меня тут похожая была, но проект был настолько здоровый, что пошагово отлаживать решался только первые 4 часа этого занятия
Щас у себя проверю...
Грибы - они разные. Один тебя накормит, другой тебе кино покажет...
Редактор журнала "
[ПРОграммист]"
Yan's Home Digital Lab
ex.cluz вне форума Ответить с цитированием
Старый 22.10.2010, 23:45   #6
Marsel737
Форумчанин
 
Аватар для Marsel737
 
Регистрация: 09.11.2009
Сообщений: 669
По умолчанию

Мда.. это какой же проект должен быть чтоб его пошагово 4 часа отлаживать.

Раз уж проблема решилась, то хочу задать ещё один вопрос пока модераторы не видят Почему потоки выполняются одинаковое время, вот лог

Цитата:
23:42:50 | ThrId: 6724 | Thread modificate file
23:42:50 | ThrId: 6808 | Thread modificate file
23:42:50 | ThrId: 6768 | Thread modificate file
23:42:50 | ThrId: 6244 | Thread modificate file
23:42:50 | ThrId: 4612 | Thread read file
23:42:50 | ThrId: 6760 | Thread read file
23:42:50 | ThrId: 6812 | Thread read file
23:42:50 | ThrId: 6804 | Thread read file
23:42:50 | ThrId: 6440 | Thread read file
23:42:50 | ThrId: 6800 | Thread modificate file
23:42:50 | ThrId: 6724 | Thread modificate file
23:42:50 | ThrId: 6808 | Thread modificate file
23:42:50 | ThrId: 6768 | Thread modificate file
23:42:50 | ThrId: 6244 | Thread modificate file
23:42:50 | ThrId: 4612 | Thread read file
23:42:50 | ThrId: 6760 | Thread read file
23:42:50 | ThrId: 6812 | Thread read file
23:42:50 | ThrId: 6804 | Thread read file
23:42:50 | ThrId: 6440 | Thread read file
23:42:50 | ThrId: 6800 | Thread modificate file
23:42:50 | ThrId: 6724 | Thread modificate file
23:42:50 | ThrId: 6808 | Thread modificate file
23:42:50 | ThrId: 6768 | Thread modificate file
23:42:50 | ThrId: 6244 | Thread modificate file
ведь считывание должно происходить гораздо дольше записи:

Код:
procedure TRd.Read;
var
  CrCh: byte;
  I: byte;
begin
  for I := 0 to 255 do
    VCh[I] := 0;
  Seek(VFile, 0);
  while not eof(VFile) do
  begin
    BlockRead(VFile, CrCh, 1);
    Inc(VCh[CrCh]);
  end;
  Writeln(VLog, TimeToStr(Time), ' | ThrId: ', IntToStr(ThrId),
    ' | Thread read file');
  OutputInfo;
end;

procedure TWr.Write;
var
  CrCh: byte;
  I: integer;
begin
  Randomize;
  for I := 0 to Random(FileSize(VFile)) div 2 do
  begin
    CrCh := Random(255);
    Seek(VFile, Random(FileSize(VFile)));
    BlockWrite(VFile, CrCh, 1);
  end;
  Writeln(VLog, TimeToStr(Time), ' | ThrId: ', IntToStr(ThrId),
    ' | Thread modificate file');
end;
Или всему виной критические секции?

UPD:

А при следующей компиляции уже такой лог:

Цитата:
23:55:16 | ThrId: 6240 | Thread read file
23:55:16 | ThrId: 6976 | Thread modificate file
23:55:16 | ThrId: 6544 | Thread modificate file
23:55:16 | ThrId: 6236 | Thread read file
23:55:16 | ThrId: 6572 | Thread read file
23:55:16 | ThrId: 6148 | Thread modificate file
23:55:16 | ThrId: 6128 | Thread modificate file
23:55:16 | ThrId: 3060 | Thread modificate file
23:55:16 | ThrId: 6204 | Thread read file
23:55:16 | ThrId: 6184 | Thread read file
23:55:16 | ThrId: 6240 | Thread read file
23:55:16 | ThrId: 6976 | Thread modificate file
23:55:16 | ThrId: 6544 | Thread modificate file
23:55:16 | ThrId: 6236 | Thread read file
23:55:16 | ThrId: 6572 | Thread read file
23:55:16 | ThrId: 6148 | Thread modificate file
23:55:16 | ThrId: 6184 | Thread read file
23:55:16 | ThrId: 3060 | Thread modificate file
23:55:16 | ThrId: 6204 | Thread read file
23:55:16 | ThrId: 6128 | Thread modificate file
23:55:16 | ThrId: 6240 | Thread read file
Потом снова такой:

Цитата:
23:42:50 | ThrId: 6800 | Thread modificate file
23:42:50 | ThrId: 6724 | Thread modificate file
23:42:50 | ThrId: 6808 | Thread modificate file
23:42:50 | ThrId: 6768 | Thread modificate file
23:42:50 | ThrId: 6244 | Thread modificate file
23:42:50 | ThrId: 4612 | Thread read file
23:42:50 | ThrId: 6760 | Thread read file
23:42:50 | ThrId: 6812 | Thread read file
23:42:50 | ThrId: 6804 | Thread read file
23:42:50 | ThrId: 6440 | Thread read file
23:42:50 | ThrId: 6800 | Thread modificate file
23:42:50 | ThrId: 6724 | Thread modificate file
23:42:50 | ThrId: 6808 | Thread modificate file
23:42:50 | ThrId: 6768 | Thread modificate file
23:42:50 | ThrId: 6244 | Thread modificate file
Почему так происходит?
Я не всегда знаю, о чем говорю, но знаю, что прав. © Мухаммед Али.
К чёрту обстоятельства. Я создаю возможности. © Брюс Ли

Последний раз редактировалось Marsel737; 22.10.2010 в 23:57.
Marsel737 вне форума Ответить с цитированием
Старый 22.10.2010, 23:48   #7
Marsel737
Форумчанин
 
Аватар для Marsel737
 
Регистрация: 09.11.2009
Сообщений: 669
По умолчанию

ошибка форума
Я не всегда знаю, о чем говорю, но знаю, что прав. © Мухаммед Али.
К чёрту обстоятельства. Я создаю возможности. © Брюс Ли
Marsel737 вне форума Ответить с цитированием
Старый 22.10.2010, 23:58   #8
ex.cluz
Участник клуба
 
Аватар для ex.cluz
 
Регистрация: 15.01.2010
Сообщений: 1,325
По умолчанию

Цитата:
Мда.. это какой же проект должен быть чтоб его пошагово 4 часа отлаживать.
Дык я еще до конца так и не дошел.
Большой, вобщем )) там еще компонентов нестандартных напихано...

Вашего вопроса не понял. По логу видно, что все происходит за одну секунду, т.е. надо миллисекунды вводить, чтоб делать выводы о том, сколько что делается.
Грибы - они разные. Один тебя накормит, другой тебе кино покажет...
Редактор журнала "
[ПРОграммист]"
Yan's Home Digital Lab
ex.cluz вне форума Ответить с цитированием
Старый 23.10.2010, 00:23   #9
Marsel737
Форумчанин
 
Аватар для Marsel737
 
Регистрация: 09.11.2009
Сообщений: 669
По умолчанию

Если не ошибаюсь, вроде бы при пошаговой компиляции при наличии сторонних компонентов приходится ещё пошагово проходиться по реализации этих компонентов, поэтому чтобы этого избежать можно нажать F4 предварительно поставив курсор на нужную строку и уже с этой строки продолжить пошагово по F7, точно так же можно пропускать длинные циклы

UPD:

Вопрос заключается в следующем, почему потоки выполняются друг за другом, ведь они работают все одновременно, причём некоторые из них работают быстрее других:

Цитата:
23:42:50 | ThrId: 6800 | Thread modificate file
23:42:50 | ThrId: 6724 | Thread modificate file
23:42:50 | ThrId: 6808 | Thread modificate file
23:42:50 | ThrId: 6768 | Thread modificate file
23:42:50 | ThrId: 6244 | Thread modificate file
23:42:50 | ThrId: 4612 | Thread read file
23:42:50 | ThrId: 6760 | Thread read file
23:42:50 | ThrId: 6812 | Thread read file
23:42:50 | ThrId: 6804 | Thread read file
23:42:50 | ThrId: 6440 | Thread read file
23:42:50 | ThrId: 6800 | Thread modificate file
23:42:50 | ThrId: 6724 | Thread modificate file
23:42:50 | ThrId: 6808 | Thread modificate file
23:42:50 | ThrId: 6768 | Thread modificate file
23:42:50 | ThrId: 6244 | Thread modificate file
Я не всегда знаю, о чем говорю, но знаю, что прав. © Мухаммед Али.
К чёрту обстоятельства. Я создаю возможности. © Брюс Ли

Последний раз редактировалось Marsel737; 23.10.2010 в 00:31.
Marsel737 вне форума Ответить с цитированием
Старый 23.10.2010, 00:34   #10
ex.cluz
Участник клуба
 
Аватар для ex.cluz
 
Регистрация: 15.01.2010
Сообщений: 1,325
По умолчанию

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

А компоненты есть и по работе с файлами, поэтому и их код смотреть надо.

Цитата:
Почему так происходит?
Что именно?
Почему такая очередность работы потоков?


Добавлено позже:
Цитата:
почему потоки выполняются друг за другом, ведь они работают все одновременно
А модифицируемый файл один и тот же? А вообще мне кажется, что это может быть случайно.
(сорри, я с кодом не разбирался, времени жалко, да и голова на ночь не варит)
Грибы - они разные. Один тебя накормит, другой тебе кино покажет...
Редактор журнала "
[ПРОграммист]"
Yan's Home Digital Lab

Последний раз редактировалось ex.cluz; 23.10.2010 в 01:00.
ex.cluz вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
страница автоматически обновляется через 1 секунду только один раз Zeron JavaScript, Ajax 5 14.06.2010 08:18
почему вылетает ошибка при передачи файлов через цокет leonw Работа с сетью в Delphi 6 19.01.2010 22:16
после скачивания 40-50 мб начинают вылазить ошибки винды Красавчег))) Windows 6 09.10.2009 22:29
Почему обработчики OnMouseWheel происходят несколько раз подряд? (Delphi7) DomiNick Общие вопросы Delphi 5 23.08.2009 22:11
WinRAR запускается через раз VitAngel Общие вопросы Delphi 0 16.02.2007 14:50