Внезапно! Access violation at adress

lexeyko

Писал-писал программу, компилировал и было все нормально и тут внезапно появилась ошибка с тем кодом, который до этого вполне исправно работал, а тут вдруг на и не хочет открывать файлы, пробовал запускать программу на другом компьютере - беда осталась, перезагружал и перекомпилировал, перестраивал проект, строил проект на другом компьютере(там вообще тихий ужас - одни ошибки, причем ошибки типа Winapi.Windows undeclared и т.п., хотя по сути и там и там эмбаркадеро одинаковой версии) - все тщетно, я уже и не знаю что делать, спасайте!!!111
procedure TForm1.Button1Click(Sender: TObject);
var
  bufferStr:string;
  temp1:string;
  temp2:string;
  currentStr:string;
  text:TextFile;
  i:integer;
  j:integer;
  l:integer;
  k:boolean;
  sentenceCount:integer;
  sentenceExist:TStringList;
  punct: set of char;
  sentenceEnd: set of char;
begin
StringGrid1.RowCount:=2;
StringGrid1.CleanupInstance;
Words:=TStringList.Create;
Sentences:=TStringList.Create;
sentenceExist:=TStringList.Create;
punct:=[',',' ',';',':','"'];
sentenceEnd:=['.','!','?'];
sentenceCount:=1;
sentenceExist.Add('0');
i:=1;
k:=false;
if OpenTextFileDialog1.Execute then
  begin
    AssignFile(text,OpenTextFileDialog1.FileName);
    reset(text);
    while not Eof(text) do
      begin
        readln(text,currentStr);
        currentStr:=AnsiLowerCase(currentStr);
        while i<=length(currentStr) do
        begin
          while not((currentStr[i] in punct) or (currentStr[i] in sentenceEnd)) or (i > length(currentStr)) do
          begin
            bufferStr:=bufferStr+currentStr[i];
            k:=true;
            inc(i);
          end;
          if (k = true) and (length(bufferStr)>2) then
          begin
            if (Words.Count <> 0) then
            begin
                for l := 0 to Words.Count-1 do
                  if (bufferStr = Words[l]) then
                  begin
                    k:=false;
                    if sentenceExist[l]='0' then
                      Sentences[l]:=Sentences[l]+', '+IntToStr(sentenceCount);
                  end;
                if k = true then
                begin
                  Words.Add(bufferStr);
                  sentenceExist.Add('1');
                  Sentences.Add(IntToStr(sentenceCount));
                end;
            end
            else
            begin
              Words.Add(bufferStr);
              sentenceExist.Add('1');
              Sentences.Add(IntToStr(sentenceCount))
            end;
            if (currentStr[i] in sentenceEnd) then
              begin
                inc(sentenceCount);
                for l := 0 to sentenceExist.Count-1 do
                sentenceExist[l]:='0';
              end;
            bufferStr := '';
            k:=false;
            inc(i);
          end
          else
          begin
           inc(i);
           bufferStr := '';
          end;
          if currentStr[i] in punct then inc(i);
        end;
        i := Words.Count-1;
        currentStr:='';
      end;
  end;
    closefile(text);
    l:=1;
  for i := 0 to Words.Count-1 do
  begin
    temp1:=Words[i];
    j:=i+1;
    while j<Words.Count do
    begin
      temp2:=Words[j];
      if (temp1[length(temp1)] = temp2[length(temp2)]) and
         (temp1[length(temp1)-1] = temp2[length(temp2)-1])
      then
      begin
        StringGrid1.Cells[0,l]:=temp1;
        StringGrid1.Cells[1,l]:=Sentences[i];
        StringGrid1.Cells[2,l]:=temp2;
        StringGrid1.Cells[3,l]:=Sentences[j];
        inc(l);
      end;
     inc(j);
    end;
  end;
  StringGrid1.RowCount:=l;
end;
Знаю букаф много но как есть так и есть, одно могу сказать - если убрать цикл while not((currentStr[i] in punct) or (currentStr[i] in sentenceEnd)) or (i > length(currentStr)) do то ошибки обращения в неверный участок памяти нет, что очень странно
2 ответа

lexeyko

вероятно вот здесь i становится больше чем длина строки, т.к. сработали вхождения на конце стороки
          while not((currentStr[i] in punct) or (currentStr[i] in sentenceEnd)) or (i > length(currentStr)) do
          begin
            bufferStr:=bufferStr+currentStr[i];
            k:=true;
            inc(i);
          end;
а дальше с выставленным флагом k
            if (currentStr[i] in sentenceEnd) then
              begin
                inc(sentenceCount);
                for l := 0 to sentenceExist.Count-1 do
                sentenceExist[l]:='0';
              end;
происходит обращение без проверок за конец строки


lexeyko

"Букаф" действительно много, но сразу бросается строка 40, дальше не смотрел
 bufferStr:=bufferStr+currentStr[i];
ты понимаешь, что изначально в локальных переменных "мусор"? Проинициализируй переменную
 bufferStr := '';