|
|
|
Пожалуйста, выделяйте текст программы тегом [сode=pas] … [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как «свернуть» программу в трей.
3. Как «скрыться» от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
… (продолжение следует) …
Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.
Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка — 60 дней. Последующие попытки бан.
Мат в разделе — бан на три месяца…
FindClose
, Ошибка при компиляции
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
В программе многакратно производится поиск файлов. Его я реализовал при помощи стандартных функций FindFirst, FindNext, FindClose. После того, как в разделе Uses был объявлен модуль Windows стала вылетать ошибка на строке FindClose. Как справиться с этой проблемой? |
Miscђka |
|
что за ошибка? Как организован поиск? |
Domino |
|
if FindFirst(‘*.txt’,faAnyFile,SR)=0 then repeat inc(c) //счетчик файлов until FindNext(SR)<>0; FindClose(SR); //в этой строчке компилятор ругается А на что именно ругается, точно не помню, но точно ему не нравится присутствие в этой строчке типа Cardinal. Причем, повторяю, программа компилировалась безошибочно, и перестала компилироваться после того, как изменилась строка uses: uses SysUtils, Windows; // после добавления модуля Windows стала вылетать ошибка компиляции |
Miscђka |
|
Цитата Denny, 25.10.04, 14:55 ему не нравится присутствие в этой строчке типа Cardinal ну дык, дай ему integer |
Domino |
|
Цитата ну дык, дай ему Integer Ну дык как? |
Song |
|
Цитата Denny, 25.10.04, 12:18 FindClose. После того, как в разделе Uses был объявлен модуль Windows стала вылетать ошибка на строке FindClose. Как справиться с этой проблемой? SysUtils.FindClose(.. |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Delphi: Общие вопросы
- Следующая тема
[ Script execution time: 0,0406 ] [ 16 queries used ] [ Generated: 21.09.23, 09:54 GMT ]
При использовании функции FindClose в Delphi может возникнуть ошибка, если она вызывается для уже закрытого файла или имеет неверный дескриптор файла. Это может произойти, если функция FindFirst не была вызвана перед FindClose или было вызвано несколько FindClose для одного дескриптора файла. Чтобы избежать этой ошибки, убедитесь, что FindClose вызывается только после вызова FindFirst и не вызывается несколько раз для одного и того же дескриптора файла.Пример кода на Delphi:var SearchRec: TSearchRec;begin if FindFirst('C:\Users\UserName\Documents\*.txt', faAnyFile, SearchRec) = 0 then begin // файлы найдены repeat // обработка файлов until FindNext(SearchRec) <> 0; FindClose(SearchRec); end;end;
В этом примере мы ищем все файлы с расширением .txt в директории пользователя и проходимся по каждому найденному файлу до тех пор, пока не будут найдены все файлы и не будет вызвана функция FindClose для закрытия дескриптора файла. Обратите внимание, что несоблюдение порядка вызовов FindFirst, FindNext и FindClose может привести к ошибке или утечке ресурсов.
How to Install Delphi 10.4 on Windows 10/11 FREE
Функции и возможности Delphi DS150E
Программирование в Delphi. Урок 13.1. Отладка, поиск ошибок Debug
Embarcadero Delphi Обзор преимуществ / Установка / Удаление / Community Edition IDE / 2022 Бесплатно
Восстановление прошивки AutoCom CDP+ из состояния кирпича (горит красным и не прошивается)
Delphi 2021/ 2022 Probleme ( An internal error has occurred )
Victor031 0 / 0 / 1 Регистрация: 11.05.2013 Сообщений: 29 |
||||
1 |
||||
03.11.2013, 23:08. Показов 1311. Ответов 3 Метки нет (Все метки)
Доброго времени суток, уважаемые! Суть проблемы в следующем: делфи ругается на процедуру FindClose. Подскажите в чем ошибка? Зараннее спасибо!
Скрин:
0 |
angstrom |
|
03.11.2013, 23:44 |
2 |
Ошибка выше, нет точки с запятой. |
cotseec Пишу на Delphi…иногда 1423 / 1278 / 286 Регистрация: 03.12.2012 Сообщений: 3,914 Записей в блоге: 5 |
||||
03.11.2013, 23:46 |
3 |
|||
в строке перед FindClose
поставь точку с запятой
1 |
0 / 0 / 1 Регистрация: 11.05.2013 Сообщений: 29 |
|
04.11.2013, 00:01 [ТС] |
4 |
Благодарствую!
0 |
The following is a snippet of code from my ap:
var DirInfo: TSearchRec;
begin
ChDir(ThisDir);
SInfo := 0;
N := FindFirst(‘*.*’,faDirector
While N = 0 do
begin
If (DirInfo.Name <> ‘.’) AND (DirInfo.Name <> ‘..’) AND (DirInfo.Attr = faDirectory) then
begin
SInfo := SInfo+1;
SetInfo[SInfo].Path := ThisDir+’\’+DirInfo.Name;
end;
N := FindNext(DirInfo);
end;
FindClose(DirInfo);
end;
When I try to compile it I get the error message «Incompatible types: «Cardinal» and «TSearchRec» on the line FindClose(DirInfo);
What am I doing wrong?
Topic: FindClose(FileInfo) — wierd error (Read 8866 times)
EDIT — I’ve just re-checked the declaration and find that the second project is using a different FilUtilh.inc file which declares FindClose as
Procedure FindClose (Var F : TUnicodeSearchrec);
I haven’t specified anything different as far as ‘INC’ paths are concerned in fact that is another question I have been meaning to ask — where DO you set a specific ‘INC’ folder? but more important for now how can I force the first project’s FilUtilh.inc file to be used?
Second EDIT — On closer reading I now see that FindClose is declared twice in the same .INC file.
Is there anything wrong with me commenting out the ‘TUnicodeSearchrec’ version? along with the FindFirst and FindNext TUnicodeSearchrec versions?
======================================
I have two projects using similar code to read filenames from disk. FindFirst is followed by FindNext and finally FindClose.
One project (with this procedure) :
-
procedure FindLogs;
-
Var
-
FileInfo : TSearchRec;
-
i : byte;
-
begin
-
Form1.LogList.Items.Clear;
-
if FindFirst(DataPath+‘*.log’,faAnyFile,FileInfo) = 0 then
-
begin
-
Form1.LogList.Items.Add(FileInfo.Name);
-
Repeat
-
if FindNext(FileInfo)=0 then
-
begin
-
Form1.LogList.Items.Add(FileInfo.Name);
-
end;
-
until FindNext(FileInfo)<>0;
-
end;
-
FindClose(FileInfo);
-
end;
compiles and runs perfectly.
The second — with this code :
-
procedure FindFiles;
-
Var
-
FileInfo : TSearchRec;
-
i,p : byte;
-
begin
-
Form1.Height := 440;
-
ReadPath;
-
i := 0;
-
if FindFirst(MusicPath+‘*.pdf’,faAnyFile,FileInfo) = 0 then
-
begin
-
P_List[i] := FileInfo.Name;
-
Repeat
-
inc(i);
-
if FindNext(FileInfo)=0 then
-
begin
-
P_List[i] := FileInfo.Name;
-
end;
-
until (FindNext(FileInfo)<>0) or (i=21);
-
end;
-
FindClose(FileInfo);
-
end;
Won’t compile, complaining Error: Incompatible type for arg no. 1: Got «TRawbyteSearchRec», expected «QWord» at FindClose(FileInfo).
I’ve checked that both projects are set to the same ‘bittness’ (actually tried both 32 and 64).
I’ve also checked the declaration of FindClose in FilUtilh.inc which is :
Procedure FindClose (Var F : TRawByteSearchrec);
so fail to understand why it’s expecting a QWord.
In the second project, I need to go on to find other files (with a different extension) so assume that I need to call FindClose before doing so.
« Last Edit: June 13, 2017, 08:10:17 pm by J-G »
Logged
FPC 3.0.0 — Lazarus 1.6 &
FPC 3.2.2 — Lazarus 2.2.0
Win 7 Ult 64
I have two projects using similar code to read filenames from disk. FindFirst is followed by FindNext and finally FindClose.
Just to nit-pick, but you are calling FindClose() in the wrong place. It should be inside the first ‘if’ block. Don’t call FindClose() if FindFirst() fails:
-
if FindFirst(DataPath+‘*.log’,faAnyFile,FileInfo) = 0 then
-
begin
-
…
-
FindClose(FileInfo); // <— here
-
end;
-
// <— not here!
Also, a better way to write the loops you have shown would look more like this instead:
1.
-
procedure FindLogs;
-
var
-
FileInfo : TSearchRec;
-
begin
-
Form1.LogList.Items.BeginUpdate;
-
try
-
Form1.LogList.Items.Clear;
-
if FindFirst(DataPath + ‘*.log’, faAnyFile, FileInfo) = 0 then
-
try
-
repeat
-
Form1.LogList.Items.Add(FileInfo.Name);
-
until FindNext(FileInfo) <> 0;
-
finally
-
FindClose(FileInfo);
-
end;
-
finally
-
Form1.LogList.Items.EndUpdate;
-
end;
-
end;
2.
-
procedure FindFiles;
-
var
-
FileInfo : TSearchRec;
-
i : byte;
-
begin
-
Form1.Height := 440;
-
for i := 0 to 20 do begin
-
P_List[i] := »;
-
end;
-
ReadPath;
-
i := 0;
-
if FindFirst(MusicPath + ‘*.pdf’, faAnyFile, FileInfo) = 0 then
-
try
-
repeat
-
P_List[i] := FileInfo.Name;
-
inc(i);
-
until (i = 21) or (FindNext(FileInfo) <> 0);
-
finally
-
FindClose(FileInfo);
-
end;
-
end;
Alternatively:
-
procedure FindFiles;
-
var
-
FileInfo : TSearchRec;
-
i : byte;
-
begin
-
Form1.Height := 440;
-
for i := 0 to 20 do begin
-
P_List[i] := »;
-
end;
-
ReadPath;
-
if FindFirst(MusicPath + ‘*.pdf’, faAnyFile, FileInfo) = 0 then
-
try
-
for i := 0 to 20 do
-
begin
-
P_List[i] := FileInfo.Name;
-
if FindNext(FileInfo) <> 0 then
-
Break;
-
end;
-
finally
-
FindClose(FileInfo);
-
end;
-
end;
Won’t compile, complaining Error: Incompatible type for arg no. 1: Got «TRawbyteSearchRec», expected «QWord» at FindClose(FileInfo).
That means the compiler is trying to call the Win32 API FindClose() function instead of the RTL’s SysUtils FindClose() function. The Win32 API function takes a HANDLE as input, that is where the QWord is coming from (when you are compiling for 64bit). You likely have the Windows unit after the SysUtils unit in your ‘uses’ clause, causing the Win32 API function to take priority. Either swap the units around, or else quality which function you intended to call:
-
if FindFirst(DataPath+‘*.log’,faAnyFile,FileInfo) = 0 then
-
begin
-
…
-
SysUtils.FindClose(FileInfo); // <— here
-
end;
I’ve checked that both projects are set to the same ‘bittness’ (actually tried both 32 and 64).
Bitness has nothing to do with this. It is a naming comflict. Delphi has the same problem.
In the second project, I need to go on to find other files (with a different extension) so assume that I need to call FindClose before doing so.
You always have to call FindClose() regardless, or else you will leak OS resources.
« Last Edit: June 13, 2017, 08:17:11 pm by Remy Lebeau »
Logged
…Error: Incompatible type for arg no. 1: Got «TRawbyteSearchRec», expected «QWord»[/color] at FindClose(FileInfo).
Specify explicitly SysUtils.FindClose. In the second case, most likely you have the function Windows.FindClose.
Additional. In the first example, you skip half of all files, because each FindNext retrieves one file at a time. Two calls FindNext (FileInfo) = 0 and FindNext (FileInfo) <> 0, but one addition of the file.
There should be the following scheme:
-
FoundFile := FindFirst(…, FileInfo) = 0;
-
try
-
while FoundFile do
-
begin
-
// Work with FileInfo
-
FoundFile := FindNext(FileInfo) = 0;
-
end;
-
finally
-
SysUtils.FindClose(FileInfo);
-
end;
@Remy Lebeau
In FPC, unlike Delphi, FindClose should be called regardless of the success of FindFirst. See docs.
Logged
@Remy Lebeau
In FPC, unlike Delphi, FindClose should be called regardless of the success of FindFirst. See docs.
That’s not: unlike Delphi
That’s always the case. Specifically under windows the handle won’t get released until program termination….
Remy should know better.
Logged
I actually get compliments for being rude… (well, Dutch, but that is the same)
In FPC, unlike Delphi, FindClose should be called regardless of the success of FindFirst. See docs.
The statement in the doc is a little ambiguous to me. Does it mean that FindClose() must always be called even if FindFirst() fails, or only if it succeeds? Does FindFirst() always allocate memory that is then not freed if FindFirst() subsequently fails? If so, why does it not free the memory before exiting? That smells like a design bug to me.
Logged
In FPC, unlike Delphi, FindClose should be called regardless of the success of FindFirst. See docs.
The statement in the doc is a little ambiguous to me. Does it mean that FindClose() must always be called even if FindFirst() fails, or only if it succeeds? Does FindFirst() always allocate memory that is then not freed if FindFirst() subsequently fails? If so, why does it not free the memory before exiting? That smells like a design bug to me.
The best docs for that are on MSDN. But anyway, to answer your question: if the allocation of the handle fails, findclose is not necessary. Because there’s nothing to close… https://msdn.microsoft.com/en-us/library/windows/desktop/aa364413(v=vs.85).aspx
ASerge was merely incomplete but essentially correct.
So note that the same goes for Delphi.
« Last Edit: June 13, 2017, 08:27:08 pm by Thaddy »
Logged
I actually get compliments for being rude… (well, Dutch, but that is the same)
That’s not: unlike Delphi
That’s always the case. Specifically under windows the handle won’t get released until program termination….
Remy should know better.
Actually, I do know better. In Delphi, if FindFirst() fails, it calls FindClose() before exiting (and always has), thus any subsequent FindClose() in user code would be a no-op. FindClose() in user code is only meaningful if FindFirst() succeeds. I would expect FPC to have the same behavior, for compatibility when porting Delphi code to FPC.
Logged
The best docs for that are on MSDN. But anyway, to answer your question: if the allocation of the handle fails, findclose is not necessary. Because there’s nothing to close… https://msdn.microsoft.com/en-us/library/windows/desktop/aa364413(v=vs.85).aspx
I understand that. But at least in Delphi, FindFirst() does more than then call FindFirstFile() by itself. It may ALSO call FindNextFile() (potentially more than once) to take the ExcludeAttr into account, so it may have to skip files before returning the first matching file. If THAT fails, FindFirst() calls FindClose() before exiting. FindNext() also performs the same ExcludeAttr skipping loop, so it may have to call FindNextFile() more than once. But, if that fails, FindNext() does not call FindClose() before exiting, it requires the caller to call it instead.
I would expect the same from FPC.
« Last Edit: June 13, 2017, 08:31:15 pm by Remy Lebeau »
Logged
Actually, I do know better. In Delphi, if FindFirst() fails, it calls FindClose() before exiting (and always has), thus any subsequent FindClose() in user code would be a no-op. FindClose() in user code is only meaningful if FindFirst() succeeds. I would expect FPC to have the same behavior, for compatibility when porting Delphi code to FPC.
So you rely on implementation detail? Anyway. In this case (but I will check it, because I am not convinced) this would work in most but not all cases:
Because it does not check the fail reason and if findfirst fails because of a failing handle allocation that is sh*t code because there is nothing to close anyway????
Agree??
Logged
I actually get compliments for being rude… (well, Dutch, but that is the same)
So you rely on implementation detail?
Yes, because that is the most accurate way to know how something really works. Documentation is not always accurate.
Anyway. In this case (but I will check it, because I am not convinced) this would work in most but not all cases
I assure you, it works the way I described. I have Delphi’s RTL/VCL/FMX source code for almost all Delphi versions from Delphi 5 all the way up to 10.0 Seattle (I’m missing 1-4, 7-8, and 2005). I looked at them before posting my replies here.
If you look at the various Delphi implementations over the years, you can see that any failure inside of FindFirst() will call FindClose() before exiting if the search handle has been allocated.
« Last Edit: June 13, 2017, 11:58:28 pm by Remy Lebeau »
Logged
Which is dumb programming? Agree??
By now I have looked at the code (and in my own copies of D5, D7, D2006 and XE2). Since that is copyrighted. Plz edit your post.
Logged
I actually get compliments for being rude… (well, Dutch, but that is the same)
According to FPC documentation, you should always call FindClose. This contradicts the general idea (also supported by Microsoft) that if there is an error in resource allocation, you do not need to release it. Delphi supports this concept within itself, ie. there it is correct to do, like you, call FindClose only after a successful FindFirst. Moreover, in earlier versions of Delphi there was a run-time error if there was an «extra» FindClose. Then they were safe from such a mistake, because many newcomers did not understand the concept.
In FPC, there is no implementation for such idea, so you always need to call FindClose.
Logged
It seems I’m adept at stirring a Hornet’s Nest
Many thanks to Remy for pointing out where my error lay — quite right about Windows being after SysUtils. I only added Windows when I needed to test for the internet being available and stupidly simply added it to the end of my Uses Clause — I hope that is a useful lesson learned — just never occurred to me
Also thanks to ASerge and Remy for pointing out the inefficient loops — all now replaced.
Logged
FPC 3.0.0 — Lazarus 1.6 &
FPC 3.2.2 — Lazarus 2.2.0
Win 7 Ult 64
In FPC, there is no implementation for such idea, so you always need to call FindClose.
Nope. Nonsense. You should just check on findfirst… on all platforms. I will put in a bug report. If findfirst fails, also on fpc, no need to call findclose.
You do not understand the stupidity of the Delphi code…. But you are smart, You read what MSDN says…. The Delphi code does basically nothing in the most likely case. And circumvented that later by preventing a second call… That’s why… Now, you agree too
Note this stupidity is not platform specific. It is stupid on ANY file handle.
[edit]
I put in the bug report against documentation.
https://bugs.freepascal.org/view.php?id=32012
« Last Edit: June 13, 2017, 11:16:00 pm by Thaddy »
Logged
I actually get compliments for being rude… (well, Dutch, but that is the same)
If findfirst fails, also on fpc, no need to call findclose.
NEED!
-
program Project1;
-
{$APPTYPE CONSOLE}
-
uses Windows, SysUtils;
-
function GetProcessHandleCount(hProcess: THandle;
-
out pdwHandleCount: DWORD): BOOL; stdcall; external kernel32;
-
function HandleCount: DWORD;
-
begin
-
if not GetProcessHandleCount(GetCurrentProcess, Result) then
-
Result := 0;
-
end;
-
procedure ResourceLeak;
-
var
-
R: TSearchRec;
-
begin
-
if FindFirst(‘c:\Windows\Fonts’, faDirectory, R) = 0 then
-
FindClose(R);
-
end;
-
procedure NoLeak;
-
var
-
R: TSearchRec;
-
begin
-
FindFirst(‘c:\Windows\Fonts’, faDirectory, R);
-
FindClose(R);
-
end;
-
var
-
i: Integer;
-
begin
-
Writeln(‘HandleCount: ‘, HandleCount);
-
for i := 0 to 100 do
-
ResourceLeak;
-
Writeln(‘HandleCount: ‘, HandleCount);
-
for i := 0 to 100 do
-
NoLeak;
-
Writeln(‘HandleCount: ‘, HandleCount);
-
Readln;
-
end.
In Delphi no leak.
Logged