Delphi 中的 AccessViolationException - 不可能(检查一下,难以置信......)

发布于 2024-12-01 15:03:53 字数 2295 浏览 1 评论 0原文

德尔福XE。 Windows 7。

有一个函数(请参阅下面的代码)或 I:=0 会在大型项目中导致 AV 错误。在新项目中同样的功能没有报错!!!我删除了大项目中的所有内容,只留下了一个按钮和该功能。它仍然会导致错误...

一行错误:

if ISAeroEnabled then // this line is a cause
       i:=0;         // or this line

我在各处设置了断点(我检查了整个函数,我在每行上设置了断点 -> 函数中没有错误),调试器显示错误位于 i:=0;

如果要删除函数(并保留 i:=0;) -> 一切正常!

错误消息:首次机会异常,价格为 747FB727。异常类 EAccessViolation,带有消息“模块‘MngProject.exe’中地址 004AE5AF 处的访问冲突”。写入地址0017FFF8'。 Process MngProject.exe (4980)

为什么它在新项目中有效,但在我的项目中无效?

这是整个项目:http://www.2shared.com/file/UP22Om4j/Bug。 html

代码:

unit MainFormModule;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  StdCtrls;
type
  TMainForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public

    { Public declarations }
  end;

var
     mainform:tmainform;
implementation
{$R *.dfm}

function  ISAeroEnabled: Boolean;
type
  _DwmIsCompositionEnabledFunc = function(IsEnabled: PBoolean): HRESULT; stdcall;
var
  Flag                       : Boolean;
  DllHandle                  : THandle;
  OsVersion                  : TOSVersionInfo;
  DwmIsCompositionEnabledFunc: _DwmIsCompositionEnabledFunc;
begin
  Result:=False;
  ZeroMemory(@OsVersion, SizeOf(OsVersion));
  OsVersion.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);

  if ((GetVersionEx(OsVersion)) and (OsVersion.dwPlatformId = VER_PLATFORM_WIN32_NT) and (OsVersion.dwMajorVersion >= 6)) then //is Vista or Win7?
  begin
    DllHandle := LoadLibrary('dwmapi.dll');
    if DllHandle <> 0 then
    begin
      @DwmIsCompositionEnabledFunc := GetProcAddress(DllHandle, 'DwmIsCompositionEnabled');
      if (@DwmIsCompositionEnabledFunc <> nil) then
      begin
        DwmIsCompositionEnabledFunc(@Flag);
        Result:=Flag;
      end;
    end;
      FreeLibrary(DllHandle);
  end;
end;

procedure Tmainform.Button1Click(Sender: TObject);
var i:integer;
begin
    if ISAeroEnabled then // AV is here
       i:=0;              // Or here
end;
end.

Delphi XE. Windows 7.

There is a function (please see a code below) or I:=0 that causes an AV error in a big project. There is no the error with the same function in a new project!!! I deleted everything from the big project, and I left only a button and that function. It still causes the error...

A line with the error:

if ISAeroEnabled then // this line is a cause
       i:=0;         // or this line

I set breakpoints everywhere (I checked the whole function, I set breakpoints on EACH LINE -> no errors in the function), a debugger shows me that the error is in i:=0;

If to delete a function (and leave i:=0;) -> all is ok!

The error message: First chance exception at $747FB727. Exception class EAccessViolation with message 'Access violation at address 004AE5AF in module 'MngProject.exe'. Write of address 0017FFF8'. Process MngProject.exe (4980)

Why does it work in a new project but not in mine?

Here's the whole project: http://www.2shared.com/file/UP22Om4j/Bug.html

The code:

unit MainFormModule;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  StdCtrls;
type
  TMainForm = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public

    { Public declarations }
  end;

var
     mainform:tmainform;
implementation
{$R *.dfm}

function  ISAeroEnabled: Boolean;
type
  _DwmIsCompositionEnabledFunc = function(IsEnabled: PBoolean): HRESULT; stdcall;
var
  Flag                       : Boolean;
  DllHandle                  : THandle;
  OsVersion                  : TOSVersionInfo;
  DwmIsCompositionEnabledFunc: _DwmIsCompositionEnabledFunc;
begin
  Result:=False;
  ZeroMemory(@OsVersion, SizeOf(OsVersion));
  OsVersion.dwOSVersionInfoSize := SizeOf(TOSVERSIONINFO);

  if ((GetVersionEx(OsVersion)) and (OsVersion.dwPlatformId = VER_PLATFORM_WIN32_NT) and (OsVersion.dwMajorVersion >= 6)) then //is Vista or Win7?
  begin
    DllHandle := LoadLibrary('dwmapi.dll');
    if DllHandle <> 0 then
    begin
      @DwmIsCompositionEnabledFunc := GetProcAddress(DllHandle, 'DwmIsCompositionEnabled');
      if (@DwmIsCompositionEnabledFunc <> nil) then
      begin
        DwmIsCompositionEnabledFunc(@Flag);
        Result:=Flag;
      end;
    end;
      FreeLibrary(DllHandle);
  end;
end;

procedure Tmainform.Button1Click(Sender: TObject);
var i:integer;
begin
    if ISAeroEnabled then // AV is here
       i:=0;              // Or here
end;
end.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

前事休说 2024-12-08 15:03:53

尝试将 PBoolean 更改为 PBOOL

function(IsEnabled: PBOOL): HRESULT; stdcall;

var
  Flag: BOOL;

PBoolean 是一个指向 Pascal Boolean 的指针,大小为 1 个字节。 PBOOL 是一个指向 Windows(基于 C)BOOL 的指针,大小为 4 个字节。您需要匹配 Windows 期望的大小。

通常,将 Windows API 调用转换为 Delphi 时,请使用与 API 相同的命名数据类型。 Windows.pas 具有将这些映射到 Delphi 类型的类型定义,例如 type BOOL = LongBool;

另外,在 Delphi 中通常(但不是必需)将指针参数更改为 var。 var 参数是用于传递引用的 Pascal 语法糖,在 C 中不可用。

function(var IsEnabled: BOOL): HRESULT; stdcall;
....
    DwmIsCompositionEnabledFunc(Flag); // no @ operator

注意: 我无法测试这一点,因为我只有 XP 可用。

Try changing PBoolean to PBOOL

function(IsEnabled: PBOOL): HRESULT; stdcall;

var
  Flag: BOOL;

PBoolean is a pointer to a Pascal Boolean which is 1 byte in size. PBOOL is a pointer to a Windows (C based) BOOL, which is 4 bytes in size. You need to match the size expected by windows.

In general, when translating Windows API calls to Delphi, use the same named data type as the API. Windows.pas has type definitions mapping these to Delphi types, e.g. type BOOL = LongBool;

Also it is usual (but not required) in Delphi to change pointer parameters to var. A var parameter is Pascal syntactic sugar for pass-by-reference which isn't available in C.

function(var IsEnabled: BOOL): HRESULT; stdcall;
....
    DwmIsCompositionEnabledFunc(Flag); // no @ operator

NOTE: I can't test this, as I only have XP available.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文