Delphi XE2:调用WinAPI EnumResourceNames会导致Win64平台中的访问冲突 [英] Delphi XE2: Invoke WinAPI EnumResourceNames cause access violation in Win64 platform

查看:98
本文介绍了Delphi XE2:调用WinAPI EnumResourceNames会导致Win64平台中的访问冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Delphi XE2 Win32平台上运行以下代码即可。但是,如果在调试模式下运行,则在win64平台上编译的同一代码将在 EnumRCDataProc中导致访问冲突:

Running the following code in Delphi XE2 Win32 platform works. However, the same code compile in win64 platform will cause access violation in "EnumRCDataProc" if run in debug mode:

procedure TForm2.Button1Click(Sender: TObject);
  function EnumRCDataProc(hModule: THandle; lpszType, lpszName: PChar; lParam:
      NativeInt): Boolean; stdcall;
  begin
    TStrings(lParam).Add(lpszName);
    Result := True;
  end;

var k: NativeInt;
    L: TStringList;
    H: THandle;
begin
  H := LoadPackage('resource.bpl');
  L := TStringList.Create;
  try
    EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L));
    ShowMessage(L.Text);
  finally
    L.Free;
    UnloadPackage(H);
  end;
end;

在Win64平台上的Delphi XE2 IDE中调试代码时,我发现EnumRCDataProc中hModule的值不与变量H不匹配。我怀疑我为EnumRCDataProc构造的参数可能有问题。但是,我不知道怎么做。有想法吗?

When debug the code in Delphi XE2 IDE on Win64 platform, I found the value of hModule in EnumRCDataProc doesn't match with variable H. I suspect that might be something wrong about the parameters I constructed for the EnumRCDataProc. However, I can't figure out how. Any ideas?

推荐答案

问题是您已经制作了 EnumRCDataProc a当地程序。您需要将其移到方法之外。

The problem is that you have made EnumRCDataProc a local procedure. You need to move it outside the method.

function EnumRCDataProc(hModule: HMODULE; lpszType, lpszName: PChar; lParam:
    NativeInt): BOOL; stdcall;
begin
  TStrings(lParam).Add(lpszName);
  Result := True;
end;

procedure TForm2.Button1Click(Sender: TObject);
var k: NativeInt;
    L: TStringList;
    H: HMODULE;
begin
  H := LoadPackage('resource.bpl');
  L := TStringList.Create;
  try
    EnumResourceNames(H, RT_RCDATA, @EnumRCDataProc, NativeInt(L));
    ShowMessage(L.Text);
  finally
    L.Free;
    UnloadPackage(H);
  end;
end;

在第一次检查时,我希望编译器会产生您的代码错误:

On first inspection I expected that the compiler would emit an error with your code:


E2094分配给过程变量的本地过程/函数回调

E2094 Local procedure/function 'Callback' assigned to procedure variable

但事实并非如此。我进行了更深入的挖掘,发现 EnumResourceNames 的回调参数声明为类型 Pointer 。如果标头转换已将其声明为类型化的回调参数,则确实会发出上述错误消息。在我看来,标题翻译在这方面很差。放弃类型系统的安全性似乎无济于事。

But it does not do so. I dug a little deeper and discovered that the callback parameter for EnumResourceNames is declared as type Pointer. If the header translation had declared this as a typed callback parameter then the above error message would indeed have been emitted. To my mind the header translation is poor in this regard. There seems very little to be gained from abandoning the safety of the type system.

您的代码在32位代码中工作的事实只是一个偶然的巧合,这取决于实现细节。您的运气用完了64位。同样,如果启用了类型检查系统,则编译器可能会立即告诉您出了什么问题。

The fact that your code works in 32 bit code is just a happy coincidence that relies on implementation details. Your luck runs out on 64 bit. Again, if the type checking system had been enabled, the compiler could have told you what was wrong immediately.

一些其他注释:


  1. EnumRCDataProc 的声明中有几个错误的类型: hModule 的类型应为 HMODULE ,函数结果应为 BOOL

  2. LoadPackage 是获得模块句柄的一种相当重量级的方法。我希望看到 LoadLibraryEx LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE LOAD_LIBRARY_AS_IMAGE_RESOURCE 选项。 / li>
  1. The EnumRCDataProc has a couple of incorrect types in its declaration: hModule should be of type HMODULE and the function result should be BOOL.
  2. LoadPackage is a rather heavyweight approach to getting a module handle. I would prefer to see LoadLibraryEx with the LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE and LOAD_LIBRARY_AS_IMAGE_RESOURCE options.

这篇关于Delphi XE2:调用WinAPI EnumResourceNames会导致Win64平台中的访问冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆