embarcadero delphi和widechar:简单的功能不起作用

时间:2011-06-08 13:08:44

标签: delphi

我真的不明白为什么这个功能不起作用:

function GetNomRepertoireTemporaire:WideString;
var
  PathLocal : array[0..MAX_PATH+1] of WideChar;
begin
  Result := '';
  if GetTempPath(SizeOf(PathLocal)-1, PathLocal)>0 then
  begin
    Result := PathLocal;
  end;
end;

我称之为:

var
  t : wideString;
initialization
  t := GetNomRepertoireTemporaire;

我等了10秒,然后我得到AV at 0x000000 address 0000000

任何人都可以解释一下我做错了什么?

5 个答案:

答案 0 :(得分:5)

您应该在代码中使用Length而不是SizeOf:

function GetNomRepertoireTemporaire:WideString;
var
  PathLocal : array[0..MAX_PATH] of WideChar;
begin
  Result := '';
  if GetTempPath(Length(PathLocal), PathLocal)>0 then
  begin
    Result := PathLocal;
  end;
end;

上面的代码假设您使用的是Unicode Delphi版本。正如David在评论中提到的,您可以更改函数以使其与Unicode和非Unicode Delphi兼容:

function GetNomRepertoireTemporaire:String;
var
  PathLocal : array[0..MAX_PATH] of Char;
begin
  Result := '';
  if GetTempPath(Length(PathLocal), PathLocal)>0 then
  begin
    Result := PathLocal;
  end;
end;

说明:GetTempPath函数用它接收的整个缓冲区填充零。 OP代码设置无效的缓冲区大小(实际大小的两倍),因此该函数将PathLocal变量后面的内存归零,从而产生AV。

答案 1 :(得分:4)

虽然这不能直接回答这个问题,但最好是调用内置的RTL方法IOUtils.TPath.GetTempPath

答案 2 :(得分:2)

如果您阅读API GetTempPath的帮助文件,您将在TCHAR中看到第一个参数是缓冲区的大小。 (即缓冲区中的字符数)

现在,您正在为函数提供缓冲区中的字节数,这是字符数的两倍。

像这样更改你的功能:

if GetTempPath(Length(PathLocal)-1, PathLocal)>0 then 

答案 3 :(得分:0)

您可以使用普通字符串处理此问题,并完全避免使用array of char。这是处理Windows api调用的好方法,因为您可以动态设置缓冲区的长度,SetLength函数可以与AnsiStrings以及WideStrings一起使用。

function GetNomRepertoireTemporaire: String;
var
  iSize: DWORD;
begin
  SetLength(Result, MAX_PATH);
  iSize := GetTempPath(MAX_PATH, PChar(Result));
  // reduce buffer to the effectively used size. if the api call
  // was successful, the terminating #0 is not included in iSize.
  SetLength(Result, iSize);
end;

如果使用AnsiString或WideString,Delphi版本将决定。

答案 4 :(得分:-1)

我在阅读您的源代码时遇到了两件事。

第一个是对方法本身的调用。我发现函数GetTempPath的信息表明参数应该是Char(8位字符)。如果你真的需要宽字符串中的临时路径,你可能必须在调用GetTempPath之后将获得的路径转换为宽字符表示(只是一个猜测,因为我手边没有API文档)。

第二点是传递第二个参数。根据{{​​3}},您必须提供指向字符数组的指针。因此,对于您的示例,调用应该看起来像

if GetTempPath(MAX_PATH, @PathLocal) > 0 then

希望它有所帮助。