Delphi中的AccessViolationException - 不可能(检查,令人难以置信的...) [英] AccessViolationException in Delphi - impossible (check it, unbelievable...)
问题描述
有一个函数(请参阅下面的代码)或 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屋!