Разработчики, работающие с Delphi, иногда сталкиваются с проблемой переполнения стека при использовании функций Windows API. Это может произойти, когда некорректно обрабатываются строки или не учитываются особенности работы с памятью в операционных системах семейства Windows.
Описание проблемы
Пользователь столкнулся с переполнением стека при попытке поддержки перетаскивания файлов из Проводника Windows. При вызове функции TDirectory.GetFiles происходит ошибка, связанная с переполнением стека. Проблема возникает из-за неправильной обработки строк, получаемых из Windows API.
Пример кода, вызывающего ошибку
В коде, предоставленном пользователем, для строки CurrFile сначала выделяется память с учетом нулевого символа, а затем пытаются удалить его, что приводит к ошибке:
SetLength(CurrFile, NameLen); //+1 для NULL
SetLength(CurrFile, StrLen(PWideChar(CurrFile)));
Подтвержденный ответ
Для решения проблемы необходимо корректно обрабатывать строки, полученные из Windows API. В частности, при выделении памяти для строки не нужно учитывать нулевой символ, так как строки в Delphi автоматически включают его.
Исправленный код
uses
ShellApi, System.IOUtils;
procedure TFormMain.CreateWnd;
begin
inherited;
DragAcceptFiles(Self.Handle, True);
end;
procedure TFormMain.WMDropFiles(var Msg: TMessage);
var
hDrop: THandle;
FileCount, NameLen, i: Integer;
CurrFile: String;
FileSysEntries: TArray<String>;
begin
hDrop := Msg.wParam;
try
FileCount := DragQueryFile(hDrop, $FFFFFFFF, nil, 0);
for i := 0 to FileCount - 1 do
begin
NameLen := DragQueryFile(hDrop, i, nil, 0);
SetLength(CurrFile, NameLen); // Не учитываем нулевой символ
DragQueryFile(hDrop, i, PChar(CurrFile), NameLen + 1);
if TDirectory.Exists(CurrFile) then
begin
FileSysEntries := TDirectory.GetFiles(CurrFile, '*.*', TSearchOption.soAllDirectories);
// ...
end;
end;
finally
DragFinish(hDrop);
end;
end;
Дополнительные замечания
Вызов inherited в обработчике сообщений WMDropFiles не требуется, так как базовый обработчик не выполняет никаких действий.
Функция DragAcceptFiles должна вызываться с актуальным HWND формы. Это можно сделать, переопределив метод CreateWnd или CreateParams.
Альтернативные ответы
Возможно, стоит обратить внимание на обработку случаев, когда HWND формы может быть пересоздан в процессе выполнения программы.
Рекомендуется проверить корректность работы с функцией TDirectory.GetFiles и возможные проблемы с обработкой пути, содержащего нулевой символ в конце.
Следуя этим рекомендациям, можно избежать переполнения стека при работе с Windows API в программах на Delphi.
Разработчики на Delphi сталкиваются с переполнением стека из-за неправильной обработки строк при использовании функций Windows API.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS