Delphi 中的 AccessViolationException - 不可能(检查它,难以置信......) [英] AccessViolationException in Delphi - impossible (check it, unbelievable...)
问题描述
德尔福 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屋!