gpt4 book ai didi

delphi - 我的类实例中的奇怪内存覆盖问题

转载 作者:行者123 更新时间:2023-12-03 18:38:52 25 4
gpt4 key购买 nike

这个问题与我先前问过的this问题有关。
@RRUZ提供的代码正在运行,但似乎不太正确或
我做错了。

执行GetSharedFiles后,在TMyObject实例中发生了奇怪的事情。 FMyEvent字段(应该为nil)指向一些随机数据。

我在5分钟前发现的是,如果我关闭了编译器选项中的优化功能,则重建后可以正常工作。所以也许这是一些编译器错误?

这是代码快照(Delphi 2009 Windows 7 64位):

unit Unit17;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm17 = class(TForm)
btnetst: TButton;
procedure btnTestClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

type
TMyEvent = procedure(Sender: TObject) of object;

type
TMyObject = class(TObject)
private
FMyEvent: TMyEvent;
function GetSharedFiles: TStringList;
public
property OnEvent: TMyEvent read FMyEvent write FMyEvent;
procedure DoSomething;
end;

var
Form17: TForm17;

implementation

uses
ActiveDs_TLB,
ActiveX;

function ADsGetObject(lpszPathName:WideString; const riid:TGUID; out ppObject):HRESULT; safecall; external 'activeds.dll';

{$R *.dfm}

procedure TForm17.btnTestClick(Sender: TObject);
var
MyObject: TMyObject;
begin
MyObject := TMyObject.Create;
try
MyObject.DoSomething;
finally
if Assigned(MyObject) then
MyObject.Free;
end;
end;

{ TMyObject }

procedure TMyObject.DoSomething;
var
TmpList: TStringList;
begin
try

TmpList := GetSharedFiles; //something is overwritting the memory in object and puts random data to FMyEvent?
if Assigned(FMyEvent) then
ShowMessage('WTF'); //this should not be called, and if you comment out GetSharedFiles it won't.

finally
if Assigned(TmpList) then
TmpList.Free;
end;
end;


function TMyObject.GetSharedFiles: TStringList;
var
FSO : IADsFileServiceOperations;
Resources : IADsCollection;
Resource : OleVariant;
pceltFetched : Cardinal;
oEnum : IEnumvariant;
begin
Result := TStringList.Create;
//establish the connection to ADSI
if ADsGetObject('WinNT://./lanmanserver', IADsFileServiceOperations, FSO) = S_OK then
begin
//get the resources interface
Resources := FSO.Resources;
//get the enumerator
oEnum:= IUnknown(Resources._NewEnum) as IEnumVariant;
while oEnum.Next(1, Resource, pceltFetched) = 0 do
begin
Result.Add(LowerCase(Format('%s%s%s',[Resource.Path,#9,Resource.User])));
Resource:=Unassigned;
end;
end;
end;
end.


任何想法出了什么问题?
谢谢你的时间。

最佳答案

关于此的调用约定可能应该是stdcall,而不是safecall

function ADsGetObject(lpszPathName:WideString; const riid:TGUID; out ppObject):HRESULT; safecall; external 'activeds.dll';


回顾
典型的COM函数返回 HRESULT结果。他们使用它来传递错误代码或 S_OK(如果一切正常)。使用这种类型的函数,您通常会具有以下代码:
if CallComFunction(parameters) = S_OK then
begin
// Normal processing goes here
end
else
begin
// Error condition needs to be dealt with here.
end

由于通常无法处理错误情况,因此Delphi为我们提供了 safecall伪调用约定。这不是真正的调用约定,因为实际上它在后台使用了 stdcall。它的作用是自动生成 S_OK的测试,并在失败时引发错误。因此,可以将典型的COM方法声明为以下任意一种:
function TypicalComFunction(Parameters): HRESULT; stdcall;
procedure TypicalComFunction(Parameters); safecall;

如果您不打算处理任何潜在的错误,请使用第二种形式(带有 safecall),而只需忽略潜在的异常。如果确实发生错误,Delphi将引发一个Exception,并且该异常会冒泡直到到达应用程序中可以处理该错误的位置。否则,它会冒泡直到到达应用程序的异常处理程序,然后用于向用户显示错误。
使用 safecall,上面的典型代码如下所示:
TypicalComFunction(Parameters); // raises exception on error    
// Normal processing goes here

另一方面,如果您确实需要 HRESUL,即使它与 S_OK不同,也可以使用 stdcall变体。

关于delphi - 我的类实例中的奇怪内存覆盖问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6663985/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com