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

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

问题描述

德尔福XE。 Windows 7。



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



一行错误:

 如果ISAeroEnabled然后//这行是一个原因
i:= 0; //或这行

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



如果要删除一个函数(并留下 i:= 0; ) - > 所有都可以! / p>

错误消息: $ 747FB727的第一次机会异常。异常类EAccessViolation,消息访问冲突在地址004AE5AF在模块'MngProject.exe'。写地址0017FFF8'。过程MngProject.exe(4980)



为什么在新项目中工作,但不在我的工作?



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



代码:

  unit MainFormModule; 

接口

使用
Windows,消息,SysUtils,变体,类,图形,控件,表单,
StdCtrls;
type
TMainForm = class(TForm)
Button1:TButton;
procedure Button1Click(Sender:TObject);
private
{私人声明}
public

{公开声明}
end;

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

函数ISAeroEnabled:Boolean;
type
_DwmIsCompositionEnabledFunc = function(IsEnabled:PBoolean):HRESULT; STDCALL;
var
标志:布尔;
DllHandle:THandle;
OsVersion:TOSVersionInfo;
DwmIsCompositionEnabledFunc:_DwmIsCompositionEnabledFunc;
begin
结果:= False;
ZeroMemory(@OsVersion,SizeOf(OsVersion));
OsVersion.dwOSVersionInfoSize:= SizeOf(TOSVERSIONINFO);

if((GetVersionEx(OsVersion))和(OsVersion.dwPlatformId = VER_PLATFORM_WIN32_NT)和(OsVersion.dwMajorVersion> = 6))那么//是Vista还是Win7?
begin
DllHandle:= LoadLibrary('dwmapi.dll');
如果DllHandle<> 0然后
begin
@DwmIsCompositionEnabledFunc:= GetProcAddress(DllHandle,'DwmIsCompositionEnabled');
if(@DwmIsCompositionEnabledFunc<> nil)then
begin
DwmIsCompositionEnabledFunc(@Flag);
结果:=标志;
结束
结束
FreeLibrary(DllHandle);
结束
结束

程序Tmainform.Button1Click(发件人:TObject);
var i:integer;
begin
if ISAeroEnabled then // AV is here
i:= 0; //或者这里
end;
结束。


解决方案

尝试更改 PBoolean to PBOOL

  function(IsEnabled:PBOOL) :HRESULT; STDCALL; 

var
标志:BOOL;

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



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



在Delphi中,通常(但不是必需)将指针参数更改为var 。一个var参数是用于传递参考的帕斯卡语法糖,在C中不可用。

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

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


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.

解决方案

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.

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

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