SORU
25 EKİM 2011, Salı


COM ben o iş nasıl XE2 ve kırılmış?

Güncelleme:XE2 Update 2 hata, aşağıda belirtilen düzeltmeler.

Aşağıdaki program, gerçek programından cutdown, XE2, bir istisna ile başarısız olur. Bu 2010'dan itibaren bir gerileme. Test etmek için TEKNOLOJİ var bilmiyorum ama program TEKNOLOJİ (kod TEKNOLOJİ üzerinde iyi çalışır teyit için Primož sayesinde) gayet iyi çalışıyor beklerdim.

program COMbug;

{$APPTYPE CONSOLE}

uses
  SysUtils, Variants, Windows, Excel2000;

var
  Excel: TExcelApplication;
  Book: ExcelWorkbook;
  Sheet: ExcelWorksheet;
  UsedRange: ExcelRange;
  Row, Col: Integer;
  v: Variant;

begin
  Excel := TExcelApplication.Create(nil);
  try
    Excel.Visible[LOCALE_USER_DEFAULT] := True;
    Book := Excel.Workbooks.Add(EmptyParam, LOCALE_USER_DEFAULT) as ExcelWorkbook;
    Sheet := Book.Worksheets.Add(EmptyParam, EmptyParam, 1, EmptyParam, LOCALE_USER_DEFAULT) as ExcelWorksheet;

    Sheet.Cells.Item[1,1].Value := 1.0;
    Sheet.Cells.Item[2,2].Value := 1.0;
    UsedRange := Sheet.UsedRange[LOCALE_USER_DEFAULT] as ExcelRange;
    for Row := 1 to UsedRange.Rows.Count do begin
      for Col := 1 to UsedRange.Columns.Count do begin
        v := UsedRange.Item[Row, Col].Value;
      end;
    end;
  finally
    Excel.Free;
  end;
end.

XE2 32 bit hata:

$C000001D mesaj ile gündeme özel durum sınıfı COMbug.exe proje 'sistem özel durumu (kod 0xc000001d) 0x00dd6f3e'.

Hata UsedRange.Columns ikinci yürütme oluşur.

XE2 64 bit hata:

$C0000005 mesaj ile gündeme özel durum sınıfı COMbug.exe proje 'c0000005 ACCESS_VIOLATION'

Tekrar söylüyorum, bence bu hata oluşuyor ikinci yürütme UsedRange.Columns ama 64 bit ayıklayıcı adım adım kod biraz garip bir yol, bu yüzden ben değilim 100% emin.

Bu sorun için QC report teslim oldum.

Delphi COM/otomasyon/arabirim yığın şey kapsamlı bir şekilde bozuldu sanki çok bana bakıyor. Bu XE2 benim evlatlık olarak dikkat çeken bir tamamlandı.

Herkes bu sorunun herhangi bir deneyimi var mı? Herkes bu soruna geçici bir çözüm bulmak için bir girişim, ben nasıl olarak herhangi bir ipucu ve tavsiye var mı? Gerçekten burada ne hata ayıklama benim uzmanlık alanımın dışında.

CEVAP
25 EKİM 2011, Salı


Geçici çözüm

rowCnt := UsedRange.Rows.Count;
colCnt := UsedRange.Columns.Count;
for Row := 1 to rowCnt do begin
  for Col := 1 to colCnt do begin
    v := UsedRange.Item[Row, Col].Value;
  end;
end;

Bu da çalışır (ve daha karmaşık durumlarda kullanmak için geçici bir çözüm bulmanıza yardımcı olabilir)

function ColCount(const range: ExcelRange): integer;
begin
  Result := range.Columns.Count;
end;

for Row := 1 to UsedRange.Rows.Count do begin
  for Col := 1 to ColCount(UsedRange) do begin
    v := UsedRange.Item[Row, Col].Value;
  end;
end;

Analiz

Sistem çöküyor.Kazanmak._Release uygulanmasında zaman DispCallByİD ComObj

varDispatch, varUnknown:
  begin
    if PPointer(Result)^ <> nil then
      IDispatch(Result)._Release;
    PPointer(Result)^ := Res.VDispatch;
  end;

Delphi TEKNOLOJİ bu aynı prosedür PUREPASCAL sürümü (TEKNOLOJİ çevirici bir sürümünü kullanır) farklı olsa da ...

varDispatch, varUnknown:
  begin
    if PPointer(Result)^ <> nil then
      IDispatch(Result.VDispatch)._Release;
    PPointer(Result)^ := Res.VDispatch;
  end;

... her iki durumda da çevirici kodu aynı (EDİT: doğru değil, sonunda benim notlarına bakınız)

@ResDispatch:
@ResUnknown:
        MOV     EAX,[EBX]
        TEST    EAX,EAX
        JE      @@2
        PUSH    EAX
        MOV     EAX,[EAX]
        CALL    [EAX].Pointer[8]
@@2:    MOV     EAX,[ESP 8]
        MOV     [EBX],EAX
        JMP     @ResDone

İlginçtir ki, bu ... çöküyor

for Row := 1 to UsedRange.Rows.Count do begin
  for Col := 1 to UsedRange.Columns.Count do begin
  end;
end;

... ve bu değil.

row := UsedRange.Rows.Count;
col := UsedRange.Columns.Count;
col := UsedRange.Columns.Count;

Bunun nedeni, yerel gizli değişkenler kullanılır. İlk örnekte, kodu derler ...

00564511 6874465600       push $00564674
00564516 6884465600       push $00564684
0056451B A12CF35600       mov eax,[$0056f32c]
00564520 50               push eax
00564521 8D8508FFFFFF     lea eax,[ebp-$000000f8]
00564527 50               push eax
00564528 E8933EEAFF       call DispCallByIDProc

... ve o iki kez aradı.

İkinci örnekte yığında iki farklı geçici yerlerde kullanılır ( - ??? ebp? uzaklıklar):

00564466 6874465600       push $00564674
0056446B 6884465600       push $00564684
00564470 A12CF35600       mov eax,[$0056f32c]
00564475 50               push eax
00564476 8D8514FFFFFF     lea eax,[ebp-$000000ec]
0056447C 50               push eax
0056447D E83E3FEAFF       call DispCallByIDProc
...
0056449B 6874465600       push $00564674
005644A0 6884465600       push $00564684
005644A5 A12CF35600       mov eax,[$0056f32c]
005644AA 50               push eax
005644AB 8D8510FFFFFF     lea eax,[ebp-$000000f0]
005644B1 50               push eax
005644B2 E8093FEAFF       call DispCallByIDProc

Hata oluştuğunda bir iç arabirim saklanan bu geçici konum olarak temizlenmiş, olan şey sadece zaman "için" durum infaz için ikinci kez çünkü orada bir şey zaten saklı bu arayüz - koy oraya ne zaman "için" adı ilk defa. İkinci örnekte, iki farklı yerde bu dahili arayüz her zaman 0'a başlatıldı kullanılır ve Bırakın hiç çağrılmaz.

Gerçek hata bu dahili arayüz çöp içeren ve Serbest çağrıldığında, sh!t olur.

Biraz daha kazma sonra, eski arayüzü çıkıyor bu çevirici kod XE2 sürüm bir eksik aynı "tür [ses]" talimat. mov olmadığını fark ettim ALÇAK,

IDispatch(Result)._Release;

bir hata olduğunu ve tam da olması gerektiği

IDispatch(Result.VDispatch)._Release;

Kötü RTL hata.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • ADDVOiCE

    ADDVOiCE

    28 Mayıs 2009
  • MrOctopi

    MrOctopi

    6 Aralık 2010
  • ravinderosahn

    ravinderosah

    20 Temmuz 2009