В статье рассматривается проблема рекурсивного поиска и обработки включаемых файлов и переменных в текстовых файлах на языке Object Pascal (Delphi). Мы рассмотрим существующий код и предложим решение для устранения доступа к недопустимым областям памяти (access violation), которое возникает при обработке ключевых слов, отличных от "включает".
Существующий код использует структуры данных ItemRecord, FileTree и Pages, а также рекурсивную функцию RecurseKeywords для поиска и обработки включаемых файлов и переменных в текстовых файлах. Функция использует регулярные выражения для извлечения включаемых файлов и переменных из текста файлов. Однако, при обработке ключевых слов, отличных от "включает", возникает доступ к недопустимым областям памяти.
Для решения этой проблемы, мы можем добавить проверку на существование массивов L0CodeData и L1CodeData перед доступом к ним. Кроме того, мы можем добавить проверку на существование файла, перед попыткой доступа к нему. Ниже представлен обновленный код функции RecurseKeywords:
function RecurseKeywords(pFileName: String; PageIdx: Integer; L1Index: Integer = 0): Integer;
Var
i,z, idx, idy, idz,k: Integer;
ChildCtr: Integer;
ActMem: TStringList;
s,t:string;
function GetItems(Text: String; Category: TCategory):string;
Var
RegEx: TRegex;
Match: TMatch;
begin
case Category of
caIncludes:
Match := Regex.Match(Text, '^\s*Include\s+"([0-9a-z_\-\\ :]+[\.inc|\.bas]+)"',[roignorecase]);
caVariables:
Match := Regex.Match(Text,'^\s*Dim\s+([a-z_#][0-9a-z_#]+)(?:_0-9a-z)*(\s+as\s+(bit|byte|word|dword|float|sbyte|sword|sdword|Long|slong|double|string|pin))',[roignorecase]);
end;
if match.Success then
result := match.Groups[1].Value
else
result := '';
end;
begin
Result := 0;
if not Assigned(Pages[PageIdx]) then Exit;
if not FileExists(pFileName) then Exit;
ActMem := TStringList.Create;
ActMem.LoadFromFile(pFileName);
idz := L1Index; // Set Key to first item in the level 1 list
for idy := 0 to High(Items) do begin // scan through all items
ChildCtr := 0;
for idx := 0 to ActMem.Count -1 do begin
t := trimLeft(ActMem[idx]); // remove spaces and skip empty lines.
if (t <> '') and (t[1] <> #39) and (t[1] <> #59) then begin
s := GetItems(t, TCategory(idy));
if s > '' then begin
if not Assigned(Pages[PageIdx].L0CodeData) then begin
SetLength(Pages[PageIdx].L0CodeData,0);
end;
if not Assigned(Pages[PageIdx].L1CodeData) then begin
SetLength(Pages[PageIdx].L1CodeData,0);
end;
if (High(Pages[PageIdx].L0CodeData) = -1) // if no L0 data or
or (Pages[PageIdx].L0CodeData[High(Pages[PageIdx].L0CodeData)].RecType<>TCategory(idy)) then // L0 Record type <> to Item type
SetLength(Pages[PageIdx].L0CodeData,Length(Pages[PageIdx].L0CodeData)+1); // Create new L0 entry
with Pages[PageIdx].L0CodeData[High(Pages[PageIdx].L0CodeData)] do begin
RecType := TCategory(idy);
Caption := Items[idy];
ImageIndex := 0;
lineNo := Idx;
Key := idz;
end;
SetLength(Pages[PageIdx].L1CodeData, Length(Pages[PageIdx].L1CodeData)+ 1);
with Pages[PageIdx].L1CodeData[High(Pages[PageIdx].L1CodeData)] do begin // Populate the L1 Record
RecType := TCategory(idy);
Caption := s;
ImageIndex := idy+3;
LineNo := idx;
case RecType of
caIncludes:
if FileExists(SourcePath+s) then begin
ImageIndex := 4;
SetLength(Pages, Length(Pages)+1);
Key := High(Pages);
Caption := s;
ChildCount := RecurseKeywords(SourcePath+s,Key);
end;
caVariables:
end;
ChildCount := 0;
Inc(ChildCtr);
end;
end;
end;
end;
idz := Idz + ChildCtr;
if ChildCtr > 0 then
Pages[PageIdx].L0CodeData[High(Pages[PageIdx].L0CodeData)].ChildCount := ChildCtr;
Form1.SaveToFile;
end;
ActMem.Free;
result := Length(Pages[PageIdx].L0CodeData);
end;
Также, для предотвращения доступа к недопустимым областям памяти, мы можем добавить проверку на существование файла перед попыткой загрузки его содержимого в TStringList. Обновленный код инициализации ActMem может выглядеть так:
if not FileExists(pFileName) then Exit;
ActMem := TStringList.Create;
ActMem.LoadFromFile(pFileName);
В заключение, мы рассмотрели проблему рекурсивного поиска и обработки включаемых файлов и переменных в текстовых файлах на языке Object Pascal (Delphi). Мы предложили решение для устранения доступа к недопустимым областям памяти, которое возникает при обработке ключевых слов, отличных от "включает". Мы добавили проверку на существование массивов L0CodeData и L1CodeData перед доступом к ним, а также добавили проверку на существование файла перед попыткой доступа к нему.
В статье описывается проблема рекурсивного поиска и обработки включаемых файлов и переменных в текстовых файлах на языке Object Pascal (Delphi), а также предлагается решение для устранения доступа к недопустимым областям памяти, возникающего при обработке
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.