Почему порядок имеет значение при использовании GetTempPath / GetTempFileName? - PullRequest
1 голос
/ 15 апреля 2020

Я устраняю неисправность некоторого кода, который приводит к сбою одного приложения. Cra sh происходит позже в приложении после его кода. Может быть, утечка памяти или что-то подобное? Я прослеживаю это до следующей функции:

function GetTempFileName: String;
const
  DOC_REGISTER_PREFIX = 'DR';
var
  NameBuffer: array[0..MAX_PATH] of char;
  PathBuffer: array[0..MAX_PATH] of char;
begin
   FillChar(NameBuffer, MAX_PATH, 0);
   FillChar(PathBuffer, MAX_PATH, 0);
   GetTempPath(SizeOf(PathBuffer), PathBuffer);
   Windows.GetTempFileName(PathBuffer, DOC_REGISTER_PREFIX, 0, NameBuffer);
   Result := NameBuffer;
end;

Функции работают, и возвращается временное имя файла, но это заставляет приложение обработать sh по некоторым причинам после перехода к функциям вызывающей стороны. После некоторого тестирования и сравнения с другими аналогичными функциями в Интернете, я обнаружил, что если я изменяю порядок между PathBuffer и NameBuffer при использовании GetTempPath и GetTempFileName, все работает как положено.

function GetTempFileName: String;
const
  DOC_REGISTER_PREFIX = 'DR';
var
  NameBuffer: array[0..MAX_PATH] of char;
  PathBuffer: array[0..MAX_PATH] of char;
begin
   FillChar(NameBuffer, MAX_PATH, 0);
   FillChar(PathBuffer, MAX_PATH, 0);
   GetTempPath(SizeOf(NameBuffer), NameBuffer);
   Windows.GetTempFileName(NameBuffer, DOC_REGISTER_PREFIX, 0, PathBuffer);
   Result := PathBuffer;
end;

Есть ли какое-либо объяснение этому

Ответы [ 2 ]

4 голосов
/ 15 апреля 2020

Скорее всего переполнение буфера. Если вы используете Delphi 2009+, char является 2-байтовым WideChar, а не 1-байтовым AnsiChar, в этом случае FillChar() заполняет только половину буфера (он заполняет байты, а не символы , несмотря на его название), но, что более важно, SizeOf() передаст неправильный размер GetTempPath(), что позволит ему записать больше символов, чем вы выделили. Вместо этого используйте Length(). GetTempPath() хочет количество символов, а не количество байтов.

Вам вообще не нужен FillChar(), и вам следует обратить внимание на возвращаемые значения функций API.

Попробуйте это:

function GetTempFileName: String;
const
  DOC_REGISTER_PREFIX = 'DR';
var
  NameBuffer: array[0..MAX_PATH-1] of char;
  PathBuffer: array[0..MAX_PATH-1] of char;
  Size: DWORD;
begin
  Result := '';
  Size := Windows.GetTempPath(Length(PathBuffer), PathBuffer);
  if (Size = 0) or (Size > Length(PathBuffer)) then Exit;
  if (Windows.GetTempFileName(PathBuffer, DOC_REGISTER_PREFIX, 0, NameBuffer) = 0) then Exit;
  Result := NameBuffer;
end;
0 голосов
/ 15 апреля 2020

В соответствии с документацией для GefTempFileName строка lpPathName не может быть длиннее символов MAX_PATH-14, иначе GetTempFileName завершится ошибкой.

Но в вашем примере вы передаете строку длиной MAX_PATH.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...