Delphi 中的 AccessViolationException - 不可能(检查它,难以置信......) [英] AccessViolationException in Delphi - impossible (check it, unbelievable...)

查看:32
本文介绍了Delphi 中的 AccessViolationException - 不可能(检查它,难以置信......)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

德尔福 XE.视窗 7.

Delphi XE. Windows 7.

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

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...

有错误的一行:

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

我到处都设置了断点(我检查了整个函数,我在 EACH LINE 上设置了断点 -> 函数中没有错误),调试器显示错误在 i 中:=0;

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;

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

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

错误消息:$747FB727 处的第一次机会异常.异常类 EAccessViolation 带有消息模块MngProject.exe"中地址 004AE5AF 处的访问冲突.写入地址 0017FFF8'.处理 MngProject.exe (4980)

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

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

这里是整个项目: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.

推荐答案

尝试将 PBoolean 更改为 PBOOL

function(IsEnabled: PBOOL): HRESULT; stdcall;

var
  Flag: BOOL;

PBoolean 是指向大小为 1 字节的 Pascal 布尔值的指针.PBOOL 是指向 Windows(基于 C)的 BOOL 的指针,大小为 4 个字节.您需要匹配 windows 预期的大小.

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.

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

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

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

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

注意:我无法测试这个,因为我只有 XP 可用.

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

这篇关于Delphi 中的 AccessViolationException - 不可能(检查它,难以置信......)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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