procedure TForm1.Button1Click(Sender: TObject);
var
  PRecord: ^Variant;
  RecList: TList;
  I, J: integer;
  str: string;
begin
  RecList := TList.Create;  GetMem(PRecord, sizeof(Variant));
  PRecord^ := VarArrayOf([1, '001', 'tom', StrToDate('2004-04-01')]);
  RecList.Add(PRecord);  GetMem(PRecord, sizeof(Variant));
  PRecord^ := VarArrayOf([2, '002', 'jack', date]); //第二次运行时会报Invaid variant type?
  RecList.Add(PRecord);  for I := 0 to RecList.Count - 1 do
  begin
    PRecord := RecList.Items[I];
    str := '';
    for J := VarArrayLowBound(PRecord^, 1) to VarArrayHighBound(PRecord^, 1) do
      str := str + VarToStr(PRecord^[J]) + '  ';
    ShowMessage(str);
  end;  for I := 0 to RecList.Count - 1 do
  begin
    PRecord := RecList.Items[I];
    FreeMem(PRecord);
  end;  FreeAndNil(RecList);
end;上叙代码在第一次按钮点击时没有问题,但是第二次点击时就会出现运行时错误,???

解决方案 »

  1.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      PRecord: PVariant;
      RecList: TList;
      I, J: integer;
      str: string;
      V: Variant;
    begin
      RecList := TList.Create;
      New(PRecord);
      PRecord^ := VarArrayOf([1, '001', 'tom', StrToDate('2004-04-01')]);
      RecList.Add(PRecord);  New(PRecord);
      PRecord^ := VarArrayOf([2, '002', 'jack', date]); //第二次运行时会报Invaid variant type?
      RecList.Add(PRecord);  for I := 0 to RecList.Count - 1 do
      begin
        PRecord := RecList.Items[I];
        str := '';
        for J := VarArrayLowBound(PRecord^, 1) to VarArrayHighBound(PRecord^, 1) do
          str := str + VarToStr(PRecord^[J]) + '  ';
        ShowMessage(str);
      end;  for I := 0 to RecList.Count - 1 do
      begin
        PRecord := RecList.Items[I];
        Dispose(PRecord);
      end;  FreeAndNil(RecList);
    end;
      

  2.   

    请教泮水,为何用GetMem会有问题呢?
      

  3.   

    var
      PRecord: ^Variant;
    begin
     showmessage(inttostr(sizeof(PRecord)));
     showmessage(inttostr(sizeof(Variant)));
    end;
      

  4.   

    aiirii的解释,说明了问题~~实际上PRecord占用4个字节(指针都是4个字节)~~而Variant占用16个字节~~调用GetMem(PRecord, SizeOf(Variant));语句后就多占用12字节~~对PRecord^操作时,会把4个字节后的内容修改了~~FreeMem(PRecord);就会把不受PRecord控制的东西给释放~~
      

  5.   

    上诉解释无效~~aiirii,想帮你解释可解释不通呀,分配SizeOf(Variant)是合理的呀~~
    它是指针的内容,你跳出来说说~~
      

  6.   

    //正确的答案出来了!~~
    //先看效果吧~~
    procedure TForm1.Button1Click(Sender: TObject);
    var
      PRecord: ^Variant;
      RecList: TList;
      I, J: integer;
      str: string;
    begin
      RecList := TList.Create;  GetMem(PRecord, sizeof(Variant));
      FillChar(PRecord^, SizeOf(Variant), 0); //<<<<<------------
      PRecord^ := VarArrayOf([1, '001', 'tom', StrToDate('2004-04-01')]);
      RecList.Add(PRecord);  GetMem(PRecord, sizeof(Variant));
      FillChar(PRecord^, SizeOf(Variant), 0); //<<<<<------------
      PRecord^ := VarArrayOf([2, '002', 'jack', date]); //第二次运行时会报Invaid variant type?
      RecList.Add(PRecord);  for I := 0 to RecList.Count - 1 do
      begin
        PRecord := RecList.Items[I];
        str := '';
        for J := VarArrayLowBound(PRecord^, 1) to VarArrayHighBound(PRecord^, 1) do
          str := str + VarToStr(PRecord^[J]) + '  ';
        ShowMessage(str);
      end;  for I := 0 to RecList.Count - 1 do
      begin
        PRecord := RecList.Items[I];
        FreeMem(PRecord);
      end;  FreeAndNil(RecList);
    end;//加上FillChar()对内存进行初始化就ok了~~
    //为什么?呵呵,猜想:Variant封装的是一个类型,赋值的时候它先要检测自己是什么类型,如果没有初始化,它就不知道自己是谁了!~~
      

  7.   

    function BufferToDisplay(const mBuffer; mSize: Integer): string;
    var
      I: Integer;
    begin
      Result := '';
      for I := 0 to mSize - 1 do try
        Result := Result + IntToHex(TByteArray(mBuffer)[I], 2);
      except
        Result := '';
        Exit;
      end;
    end; { BufferToDisplay }procedure TForm1.Button1Click(Sender: TObject);
    var
      PRecord: ^Variant;
    begin
      New(PRecord);
      Caption := BufferToDisplay(PRecord^, SizeOf(Variant));
      Dispose(PRecord);
    end;原来New()还要做内存初始化~~
      

  8.   

    sorry, 當時我也不是很明白, 
    但, 寫代碼多了, 有時有種反應, 直覺, 
    不知為什麼, 就寫出來!
    當然可能是對, 也可能不對!zswang 老大, 果然利害,
    貼子收藏, 有空再學習!!!//加上FillChar()对内存进行初始化就ok了~~
    我以前已經吃過 ZeroMemory 的苦頭, 
    沒想到這裹也是這樣???
    當時也是這樣, 一個dll, 老是非法地址訪問, 
    最後, GetMem 後, 再ZeroMemory 後就可以了!
    雖然一解釋, 好象很簡單, 不過, 有空我再回來看看!