简体   繁体   English

为什么使用 GetTempPath/GetTempFileName 时顺序很重要?

[英]Why does order matter when using GetTempPath/GetTempFileName?

I am troubleshooting some code that is crashing one application.我正在对一些导致一个应用程序崩溃的代码进行故障排除。 The crash is happening later in application after his code.崩溃发生在他的代码之后的应用程序中。 Maybe memory leak or something similar?也许 memory 泄漏或类似的东西? I trace it back to the following function:我将其追溯到以下 function:

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;

The functions works and it gets back a temporary filename but it makes the application to crash for some reason after going up to the caller functions.这些函数可以工作,它会返回一个临时文件名,但它会使应用程序在调用调用函数后由于某种原因崩溃。 After some testing and comparing with other similar functions online, I found out that if I change the order between PathBuffer and NameBuffer when using GetTempPath and GetTempFileName, everything works as expected.经过一些在线测试和其他类似功能的比较,我发现如果在使用 GetTempPath 和 GetTempFileName 时更改 PathBuffer 和 NameBuffer 之间的顺序,一切正常。

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;

Is there any explanation for this?对此有什么解释吗?

Most likely a buffer overflow.很可能是缓冲区溢出。 If you are using Delphi 2009+, char is 2-byte WideChar , not 1-byte AnsiChar , in which case FillChar() fills only 1/2 of the buffer (it fills bytes, not characters, despite its name), but more importantly SizeOf() would pass the wrong size to GetTempPath() , allowing it to write more chars than you have allocated space for.如果您使用的是 Delphi 2009+,则char是 2 字节WideChar ,而不是 1 字节AnsiChar ,在这种情况下FillChar()仅填充缓冲区的 1/2(它填充字节,而不是字符,尽管它的名称),但更多重要的是SizeOf()会将错误的大小传递给GetTempPath() ,允许它写入比您分配的空间更多的字符。 Use Length() instead.改用Length() GetTempPath() wants the number of chars, not the number of bytes. GetTempPath()想要字符数,而不是字节数。

You don't need FillChar() at all, and you should pay attention to the return values of the API functions.您根本不需要FillChar() ,您应该注意 API 函数的返回值。

Try this:尝试这个:

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;

Acording to documentation for GefTempFileName lpPathName string cannot be longer than MAX_PATH-14 characters or GetTempFileName will fail.根据 GefTempFileName lpPathName 字符串的文档,长度不能超过 MAX_PATH-14 个字符,否则 GetTempFileName 将失败。

But in your example you are passing string that is MAX_PATH long.但是在您的示例中,您传递的是 MAX_PATH 长的字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM