Delphi 7:访问冲突-TByteDynArray问题 [英] Delphi 7: Access violation - TByteDynArray problem

查看:287
本文介绍了Delphi 7:访问冲突-TByteDynArray问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对Delphi&必须编写一个SOAP客户端。导入WSDL会生成此代码(由于显然必须遵守服务器端,因此我显然无法更改)

I am fairly new to Delphi & have to code a SOAP client. Importing the WSDL generates this code (which I obviously can't change as I obviously have to comply with the server side)

  DataPart            = class;             
  Message             = class;             
  eMessage            = class;             

  eventType = ( send, delete, etc );

  DataPart = class(TRemotable)
  private
    FhasData: Boolean;
    Fdata: TByteDynArray;
  published
    property hasData: Boolean read FhasData write FhasData;
    property data: TByteDynArray read Fdata write Fdata;
  end;
  Message = class(TRemotable)
  private
    FMessageID: Int64;
    Ftimestamp: TXSDateTime;
    Fevent: eventType;
    FmagicNumber: WideString;
    FDataPart: DataPart;
  published
    property MessageID: Int64 read FMessageID write FMessageID;
    property timestamp: TXSDateTime read Ftimestamp write Ftimestamp;
    property event: eventType read Fevent write Fevent;
    property magicNumber: WideString read FmagicNumber write FmagicNumber;
    property DataPart: DataPart read FDataPart write FDataPart;
  end;

  eMessage = class(TRemotable)
  private
    FencryptedMessage: TByteDynArray;
    Fdata: DataPart;
  published
    property encryptedMessage: TByteDynArray read FencryptedMessage write FencryptedMessage;
    property data: DataPart read Fdata write Fdata;
  end;

  MyApplicationPortType = interface(IInvokable)
  ['{99767D33-6B4A-7547-4DAC-0608095CAC70}']

    function  sendMessage(const encryptedMessage: TByteDynArray; const data: DataPart): WideString; stdcall;
  end;

任何人都可以给我编写一个带有伪值的示例,该示例将调用sendMessage()并且不会导致访问冲突?我真的不知道如何处理TByteDynArray

Can anyone code me an example with dummy values that will call sendMessage() and not cause an access violation? I really don't know how to handle TByteDynArray

根据要求,这是我的代码,但-免责声明-发布之前,我不得不对其进行大量修改(减少),因此它可能无法编译。 sendMessage()的两个参数都不为空

as requested, here's my code, BUT - disclaimer - I had to hack it about a lot (reduce it) before posting, so it may not compile. Both parms to sendMessage() are non-null

  var theMessageArray: TByteDynArray;
      theResult : WideString;
      messageData : TByteDynArray;
      i : Integer;
begin
  theMessage.messageID := theMessage.messageID + 1;
  theMessage.timestamp := TXSDateTime.Create();
  theMessage.timestamp.AsDateTime := Now();
  theMessage.event := delete;
  theMessage.magicNumber  := 'magic # ' + IntToStr(theMessage.messageID);

  SetLength(messageData, 1);
  messageData[0] := 0;

  theMessage.dataPart.hasData := True;
  messageData := theMessage.dataPart.messageData;

  SetLength(messageData, $1000 * dataSize);

  for i := 0 to $1000 * dataSize - 1 do
        messageData[i] := i and $FF;

  theMessage.DataPart.messageData := messageData;

  theMessageArray := TByteDynArray(theMessage);
  theResult := (HTTPRIO1 as MyApplicationPortType).sendMessage(theMessageArray, theMessage.dataPart);


推荐答案

新思路:您是否进行范围检查在这个单元上?添加{$ R +}

如果要使用动态数组类型,则必须在构造函数中显式设置其长度,然后再访问它。复制/分配,您也必须非常小心。

If you want to use a dynamic array type, you must explicity set its length in the constructor before you access it, and when copying/assigning, you must be very careful as well.

不仅必须在每个TByteDynArray上调用SetLength,然后再访问其元素:

Not only must you call SetLength on each TByteDynArray before accessing its elements:

SetLength(Fdata, MyDesiredLengthWhichIsGreaterThanZero):

在这里也必须小心,我认为这可能麻烦您:

You must also be careful here, I think this could get you in trouble:

  property data: TByteDynArray read Fdata write Fdata;

您的自动生成器为您编写了该代码,如果您真的知道想要一个动态数组,您显然可以将其发布。 (更新:最初我是错的)。

Your auto-generator made that code for you, and if you really know you want a dynamic array, you apparently CAN make it published. (Updated: I was wrong about that initially).

TRemotable不能用于索引属性,但可以用于字节数组(TByteDynArray)属性,因此,如果您做对了所有事情,您不需要停止使用TByteDynArray(最初我是错的)。

TRemotable, as Rob points out, does not work with indexed properties but does work fine with "array of byte" (TByteDynArray) properties, so if you do everything right, you do not need to stop using TByteDynArray (I was wrong about that initially).

如果这是我从头开始编写的,那么我将使用字符串类型而不是TBytes。我想知道为什么它不使用TBytes,但是我知道您正在使用一些自动生成的WSDL-generator-code实现SOAP客户端。因此,鉴于此,应该非常有可能使您的代码不会崩溃。

If it was me writing this from scratch, I would use a "string" type instead like TBytes. I am wondering why it didn't use TBytes, but I understand that you are implementing a SOAP client using some auto-generated WSDL-generator-code. So given that, it should be eminently possible to make your code not crash.

另请参见此相关问题

我不知道如何编写SOAP客户端,但是它看起来您的代码做了一些狡猾的事情。看来您需要修复动态数组处理,包括Rob指出的嗯,为什么要在此处进行Cast问题。但是,看起来您也不能随意更改类型,因为看起来您必须使用TRemotable机制已知并处理的类型。

I do not know how to write a SOAP client, but it looks like your code does some dodgy things. It looks like you need to fix your dynamic array handling, including the "uh-oh, why are you doing a Cast here" problem Rob pointed out to you. However, it does not look like you are free to just change types either, as it looks like you must use types that are known by and handled by your TRemotable mechanisms.

对于您的请求,它应该可以正常工作:

As for your request, this should work:

  procedure TestMe( whatever:TWhatever );
  var 
    FData:TByteDynArray;
  begin
     SetLength(FData,2); 
     FData[0] := 10; 
     FData[1] := 20;
     sendMessage(FData, whatever);
  end;

这篇关于Delphi 7:访问冲突-TByteDynArray问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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