Различия между Delphi и FPC

Модератор: Модераторы

Различия между Delphi и FPC

Сообщение Max Rusov » 30.06.2009 00:44:41

Последний месяц занимаюсь переводом большого Delphi проекта под FPC64, цель - получить код, компилирующийся под Win32/Win64 на Delphi и FPC. Поэтому включен режим совместимости с Delphi и стараюсь, по возможности, убирать весь компиляторо-зависимый код. Неизбежно оказалось, что режим "совместимости" отнюдь не гарантирует, что программа, без ошибок работающая в Delphi будет работать и под FPC (кто бы сомневался :) ). Походил уже по многим граблям, вот, хочу поделиться опытом, может кому-нибудь еще будет полезно. С другой стороны буду благодарен если дополните список - с чем еще можно столкнуться.

Оговорюсь - приложение мое серверное, поэтому все что касается VCL/LCL и прочих визуальных форм не очень интересует. Интересует в первую очередь то, что компилируется, не выдает ошибок/предупреждений, но работает по разному.

Добавлено спустя 5 минут 14 секунд:
1. Порядок вычисления аргументов функции может измениться

Код: Выделить всё
  function Func1 :String;
  begin
    Writeln(1);
    Result := '';
  end;

  function Func2 :Integer;
  begin
    Writeln(2);
    Result := 0;
  end;

  procedure Proc3(A :String; B :Integer);
  begin
    Writeln(3);
  end;

  begin
    Proc3(Func1, Func2);



Для Delphi последовательность 1-2-3, для FPC 2-1-3. Так что, если порядок важен - так писать не следует.

Добавлено спустя 10 минут 1 секунду:
2. Из той же области, несколько менее очевидный пример.

Код: Выделить всё
  function Func1(var A :Integer) :Integer;
  begin
    Inc(A);
    Result := 1;
  end;
 

  procedure Test1;
  var
    I :Integer;
  begin
    I := 0;
    Inc(I, Func1(I));
    writeln(I);
  end;


В Delphi результат - 2. Во FPC64 зависит от опций оптимизации - либо 1 либо 2.

Добавлено спустя 11 минут 19 секунд:
3. Иной порядок деинициализации интерфейсных переменных

Код: Выделить всё
  var
    Obj1 :IUnknown;

  type
    TClass1 = class(TInterfacedObject)
    public
      destructor Destroy; override;
    end;

  destructor TClass1.Destroy;
  begin
    Writeln(Integer(Obj1));
    inherited Destroy;
  end;

  begin
    Obj1 := TClass1.Create;
    Obj1 := nil;


В Delphi, во время вызова деструктора интерфейсная переменная уже обнулена, во FPC - еще нет. Вроде мелочь, но может сильно засадить в сложных случаях когда объекты взаимно ссылаются друг на друга через интерфейсы.

Добавлено спустя 39 минут 11 секунд:
4. А вот это уже - конкретная засада, если вы активно используете интерфейсы.

Код: Выделить всё
  type
    IInterface1 = interface(IUnknown)
      procedure Proc1(Intf :IInterface1);
    end;

    TClass1 = class(TInterfacedObject, IInterface1)
    public
      destructor Destroy; override;
      procedure Proc1(Intf :IInterface1);
    end;

  destructor TClass1.Destroy;
  begin
    writeln('Destroy: ', Integer(Self));
    inherited Destroy;
  end;

  procedure TClass1.Proc1(Intf :IInterface1);
  begin
    writeln('Proc1:', Integer(Self));
  end;

  function GetInterface1 :IInterface1;
  begin
    Result := TClass1.Create;
  end;

  begin
    GetInterface1.Proc1( GetInterface1 );


Пример несколько труден для понимания. Он демонстрирует то, как метод Proc1 вызывается на уже уничтоженом объекте (то, что в этом месте не возникает AV - чистая случайность). Видимо, FPC считает, что раз интерфейс, который вернула функция GetInterface1 ничему не присвоен, то его можно сразу уничтожить.

проблему можно обойти так:

Код: Выделить всё
  with GetInterface1 do
    Proc1( GetInterface1 );


Либо, для пущей надежности, завести локальную переменную. Вот только пойди найди все такие места :(

Добавлено спустя 2 минуты 59 секунд:
5. Ну, то что Set'ы, которые в Delphi имеют SizeOf = 1 или 2 байта в FPC всегда 4 байта все знают. Неприятно только, когда эти set'ы пишутся в поток...

Добавлено спустя 7 минут 13 секунд:
6. Из неприятных различий в RTL:

Код: Выделить всё
  const
    errSomeCodeFromResource = 123;

  begin
    raise Exception.CreateRes(errSomeCodeFromResource);


В FPC всегда будет генерировать одну ошибку - AV. В FPC Exception не имеет только один вариант конструктора CreateRes (и аналогичных), который получает указатель на строку. А на этапе компиляции эта ошибка не ловится, потому что (в отличии от Delphi) в FPC указателю можно присвоить целочисленную константу...

Все, пока хватит.
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение скалогрыз » 30.06.2009 11:11:15

Max Rusov писал(а):3. Иной порядок деинициализации интерфейсных переменных

4. А вот это уже - конкретная засада, если вы активно используете интерфейсы.

Пример несколько труден для понимания. Он демонстрирует то, как метод Proc1 вызывается на уже уничтоженом объекте (то, что в этом месте не возникает AV - чистая случайность). Видимо, FPC считает, что раз интерфейс, который вернула функция GetInterface1 ничему не присвоен, то его можно сразу уничтожить.

совсем недавно этот баг исправляли в компиляторе версии 2.3.1
http://bugs.freepascal.org/view.php?id=14019
я бы предложил обновить и пересобрать fpc. и проверить остался ли баг.

Max Rusov писал(а):5. Ну, то что Set'ы, которые в Delphi имеют SizeOf = 1 или 2 байта в FPC всегда 4 байта все знают. Неприятно только, когда эти set'ы пишутся в поток...

Размер set-a в Delphi зависит от количества элементов в Set-e. Если я не ошибаюсь, то set из 17 элементов в Delphi так же будет иметь размер 4 байта ;)

В FPC размер set-а настраивается. Точнее не размер set-а а "упаковка" размера. По-умолчанию, set всегда приводится к 4 байтам, но, используя директиву компиляции, можно привести к компилятор к delphi-совместимому варианту
http://lazarus-ccr.sourceforge.net/fpcd ... 40001.1.59

Код: Выделить всё
{$ifdef fpc}{$mode delphi}{$h+}{$packset 1}{$endif}
type
  tset = set of (sa,sb);
var
  s : tset;
begin
  writeln(sizeof(s));
end.


Лучше избегать записи set-ов в поток, ибо не кроссплатформенно (intel-order, network-order)!
скалогрыз
долгожитель
 
Сообщения: 1803
Зарегистрирован: 03.09.2008 02:36:48

Re: Различия между Delphi и FPC

Сообщение Max Rusov » 30.06.2009 14:54:14

скалогрыз писал(а):совсем недавно этот баг исправляли в компиляторе версии 2.3.1
http://bugs.freepascal.org/view.php?id=14019
я бы предложил обновить и пересобрать fpc. и проверить остался ли баг.


Спасибо за наводку, а то у меня уже руки опускаются весь код переделывать. Надеюсь, этот поправлено и в FPC64?

скалогрыз писал(а):В FPC размер set-а настраивается. Точнее не размер set-а а "упаковка" размера. По-умолчанию, set всегда приводится к 4 байтам, но, используя директиву компиляции, можно привести к компилятор к delphi-совместимому варианту
http://lazarus-ccr.sourceforge.net/fpcd ... 40001.1.59


Жалко, что я раньше это не знал. Причем я искал эту опцию, но нашел только MinEnumSize...
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение Max Rusov » 01.07.2009 17:06:39

скалогрыз писал(а):совсем недавно этот баг исправляли в компиляторе версии 2.3.1
http://bugs.freepascal.org/view.php?id=14019
я бы предложил обновить и пересобрать fpc. и проверить остался ли баг.


Посмотрел, баг, действительно исчез. Но какой ценой! Теперь обращение к каждому интерфейсному полю рассматривается как функция, со всеми вытекающими - созданием темпа, incref'ами, except-фреймом... Т.е. лекарство хуже болезни. Пример:

Код: Выделить всё
  procedure TSomeClass.SomeMethod;
  begin
    NOP;
    FIntfField.IntfMethod;
    NOP;
  end;


Было (2.2.4):

Код: Выделить всё
begin
  push   ebp
  mov    ebp,esp
  sub    esp,0x4
  mov    DWORD PTR [ebp-0x4],ebx
  mov    ebx,eax
NOP;
  call   0x41bbd0 <Nop>
FIntfField.IntfMethod;
  mov    edx,DWORD PTR [ebx+0x4]
  mov    eax,edx
  mov    edx,DWORD PTR [edx]
  call   DWORD PTR [edx+0x20]
NOP;
  call   0x41bbd0 <Nop>
end
  mov    ebx,DWORD PTR [ebp-0x4]
  leave
  ret


Стало (2.3.1):

Код: Выделить всё
begin
  push   ebp
  mov    ebp,esp
  sub    esp,0x30
  mov    DWORD PTR [ebp-0x30],ebx
  mov    ebx,eax
  mov    DWORD PTR [ebp-0x2c],0x0
  lea    ecx,[ebp-0xc]
  lea    edx,[ebp-0x24]
  mov    eax,0x1
  call   0x10093a0 <fpc_pushexceptaddr>
  call   0x100aed0 <SYSTEM_SETJMP$JMP_BUF$$LONGINT>
  push   eax
  test   eax,eax
  jne    0x1001b12 <TSomeClass__SomeMethod+98>
NOP;
  call   0x101d470 <Nop>
FIntfField.IntfMethod;
  lea    eax,[ebp-0x2c]
  call   0x1008ab0 <fpc_intf_decr_ref>
  mov    DWORD PTR [ebp-0x2c],0x0
  mov    eax,DWORD PTR [ebx+0x4]
  call   0x1008ae0 <fpc_intf_incr_ref>
  lea    eax,[ebp-0x2c]
  call   0x1008ab0 <fpc_intf_decr_ref>
  mov    eax,DWORD PTR [ebx+0x4]
  mov    edx,eax
  mov    DWORD PTR [ebp-0x2c],eax
  mov    edx,DWORD PTR [edx]
  call   DWORD PTR [edx+0x20]
NOP;
  call   0x101d470 <Nop>
end;
  call   0x1009660 <fpc_popaddrstack>
  lea    eax,[ebp-0x2c]
  call   0x1008ab0 <fpc_intf_decr_ref>
  mov    DWORD PTR [ebp-0x2c],0x0
  pop    eax
  test   eax,eax
  je     0x1001b30 <TSomeClass__SomeMethod+128>
  call   0x10097c0 <fpc_reraise>
  mov    ebx,DWORD PTR [ebp-0x30]
  leave
  ret


"Тут тоска ее взяла и царица померла" (c)
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение Sergei I. Gorelkin » 01.07.2009 17:48:15

Погоди-ка... Вот в этом примере
Код: Выделить всё
program t3;
{$mode objfpc}{$h+}

type
  iintf = interface(IInterface)
    procedure DoSomething;
  end; 

  tobj = class(TObject)
    fintf: iintf;
    procedure test;
  end;

procedure tobj.test;
begin
  fintf.DoSomething;
end;

begin
end.

никаких except-фреймов не наблюдается.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Различия между Delphi и FPC

Сообщение Max Rusov » 01.07.2009 18:00:20

А у меня наблюдается. Вы на 2.3.1 смотрите?
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение Sergei I. Gorelkin » 01.07.2009 19:38:26

Да, на 2.3.1, собранный сегодня из svn специально по случаю.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Различия между Delphi и FPC

Сообщение Max Rusov » 01.07.2009 21:58:50

Чудно. Кто-то из нас ошибается. Приведите, pls, ассемблерный листинг процедуры tobj.test.
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение Sergei I. Gorelkin » 01.07.2009 23:44:56

Не вопрос. (фрагмент листинга, полученного с опциями -Amasm -s, т.е. без оптимизации)
Код: Выделить всё
_CODE      SEGMENT   PARA PUBLIC USE32 'CODE'
   ALIGN 16
   PUBLIC   P$T3_TOBJ_$__TEST
P$T3_TOBJ_$__TEST:
      push   ebp
      mov   ebp,esp
      sub   esp,8
      mov   dword ptr [ebp-4],eax
      mov   eax,dword ptr [ebp-4]
      mov   eax,dword ptr [eax+4]
      mov   dword ptr [ebp-8],eax
      mov   eax,dword ptr [ebp-8]
      mov   edx,dword ptr [ebp-8]
      mov   edx,dword ptr [edx]
      call   dword ptr [edx+12]
      leave
      ret
_CODE      ENDS
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Различия между Delphi и FPC

Сообщение Max Rusov » 02.07.2009 11:29:24

Sergei I. Gorelkin

Прошу прощения, что напрягаю, но для меня очень важно разобраться. Не могли бы Вы еще раз откомпилировать нижеприведенную программу и приаттачить ее ассемблерный листинг (желательно полный).

Код: Выделить всё
program FPTest;
{$mode delphi}

type
  iintf = interface(IUnknown)
    function GetIntf :iintf;
    procedure DoSomething;
  end;

  tobj = class(TObject)
    fintf: iintf;
    procedure test1;
    procedure test2;
  end;

procedure tobj.test1;
begin
  fintf.DoSomething;
end;

procedure tobj.test2;
begin
  fintf.GetIntf.GetIntf.DoSomething;
end;


begin
end.
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение Sergei I. Gorelkin » 02.07.2009 15:20:51

Здесь-то понятно, в конструкции test2 временная переменная нужна, потому что интерфейс возвращается функцией. Нужно заметить, что в данном случае except-фрейм формируется и в Дельфи, причем Дельфи финализирует две переменные, а не одну, как FPC. Просто в Дельфи это выглядит несколько компактнее.
Но в случае test1 берется готовый интерфейс из поля, и никакого смысла дергать его счетчик ссылок нет.
Вот листинг:
Код: Выделить всё
   .386p
DGROUP   GROUP   _BSS,_DATA
   ASSUME   CS:_CODE,ES:DGROUP,DS:DGROUP,SS:DGROUP

   EXTRN   FPC_PUSHEXCEPTADDR: NEAR
   EXTRN   FPC_SETJMP: NEAR
   EXTRN   FPC_INTF_DECR_REF: NEAR
   EXTRN   FPC_POPADDRSTACK: NEAR
   EXTRN   FPC_RERAISE: NEAR
   EXTRN   FPC_INITIALIZEUNITS: NEAR
   EXTRN   FPC_DO_EXIT: NEAR
   EXTRN   VMT_SYSTEM_TOBJECT: NEAR
   EXTRN   FPC_EMPTYINTF: NEAR
   EXTRN   SYSTEM_TOBJECT_$__DESTROY: NEAR
   EXTRN   SYSTEM_TOBJECT_$__NEWINSTANCE$$TOBJECT: NEAR
   EXTRN   SYSTEM_TOBJECT_$__FREEINSTANCE: NEAR
   EXTRN   SYSTEM_TOBJECT_$__SAFECALLEXCEPTION$TOBJECT$POINTER$$LONGINT: NEAR
   EXTRN   SYSTEM_TOBJECT_$__DEFAULTHANDLER$formal: NEAR
   EXTRN   SYSTEM_TOBJECT_$__AFTERCONSTRUCTION: NEAR
   EXTRN   SYSTEM_TOBJECT_$__BEFOREDESTRUCTION: NEAR
   EXTRN   SYSTEM_TOBJECT_$__DEFAULTHANDLERSTR$formal: NEAR
   EXTRN   INIT$_SYSTEM: NEAR
   EXTRN   INIT$_FPINTRES: NEAR
   EXTRN   INIT$_OBJPAS: NEAR
   EXTRN   FINALIZE$_OBJPAS: NEAR
   EXTRN   THREADVARLIST_SYSTEM: NEAR
; Begin asmlist al_begin
; End asmlist al_begin
; Begin asmlist al_stabs
; End asmlist al_stabs
; Begin asmlist al_procedures

_CODE      SEGMENT   PARA PUBLIC USE32 'CODE'
   ALIGN 16
   PUBLIC   P$FPTEST_TOBJ_$__TEST1
P$FPTEST_TOBJ_$__TEST1:
      push   ebp
      mov   ebp,esp
      sub   esp,8
      mov   dword ptr [ebp-8],ebx
      mov   dword ptr [ebp-4],eax
      mov   eax,dword ptr [ebp-4]
      mov   ebx,dword ptr [eax+4]
      mov   eax,ebx
      mov   edx,ebx
      mov   edx,dword ptr [edx]
      call   dword ptr [edx+16]
      mov   ebx,dword ptr [ebp-8]
      leave
      ret
_CODE      ENDS

_CODE      SEGMENT   PARA PUBLIC USE32 'CODE'
   ALIGN 16
   PUBLIC   P$FPTEST_TOBJ_$__TEST2
P$FPTEST_TOBJ_$__TEST2:
      push   ebp
      mov   ebp,esp
      sub   esp,52
      mov   dword ptr [ebp-52],ebx
      mov   dword ptr [ebp-4],eax
      mov   dword ptr [ebp-48],0
      lea   ecx,dword ptr [ebp-16]
      lea   edx,dword ptr [ebp-40]
      mov   eax,1
      call   FPC_PUSHEXCEPTADDR
      call   FPC_SETJMP
      push   eax
      test   eax,eax
      jne   @@j11
      mov   eax,dword ptr [ebp-4]
      mov   ebx,dword ptr [eax+4]
      lea   eax,dword ptr [ebp-48]
      call   FPC_INTF_DECR_REF
      mov   dword ptr [ebp-48],0
      lea   edx,dword ptr [ebp-48]
      mov   eax,ebx
      mov   ecx,ebx
      mov   ecx,dword ptr [ecx]
      call   dword ptr [ecx+12]
      mov   ebx,dword ptr [ebp-48]
      lea   eax,dword ptr [ebp-48]
      call   FPC_INTF_DECR_REF
      mov   dword ptr [ebp-48],0
      lea   edx,dword ptr [ebp-48]
      mov   eax,ebx
      mov   ecx,ebx
      mov   ecx,dword ptr [ecx]
      call   dword ptr [ecx+12]
      mov   ebx,dword ptr [ebp-48]
      mov   eax,ebx
      mov   edx,ebx
      mov   edx,dword ptr [edx]
      call   dword ptr [edx+16]
@@j11:
      call   FPC_POPADDRSTACK
      lea   eax,dword ptr [ebp-48]
      call   FPC_INTF_DECR_REF
      mov   dword ptr [ebp-48],0
      pop   eax
      test   eax,eax
      je   @@j12
      call   FPC_RERAISE
@@j12:
      mov   ebx,dword ptr [ebp-52]
      leave
      ret
_CODE      ENDS

_CODE      SEGMENT   PARA PUBLIC USE32 'CODE'
   ALIGN 16
   PUBLIC   PASCALMAIN
PASCALMAIN:
   PUBLIC   _main
_main:
      push   ebp
      mov   ebp,esp
      call   FPC_INITIALIZEUNITS
      call   FPC_DO_EXIT
      leave
      ret
; End asmlist al_procedures
; Begin asmlist al_globals
_CODE      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   IID_P$FPTEST_IINTF
IID_P$FPTEST_IINTF   DD   0
   DW   0,0
   DB   0,0,0,0,0,0,0,0
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   PUBLIC   IIDSTR_P$FPTEST_IINTF
IIDSTR_P$FPTEST_IINTF   DB   0

_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
_$FPTEST$_Ld1   DB   4
      DB   "tobj"
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   VMT_P$FPTEST_TOBJ
VMT_P$FPTEST_TOBJ   DD   8,-8,VMT_SYSTEM_TOBJECT,_$FPTEST$_Ld1,0,0,_$FPTEST$_Ld2,0,INIT_P$FPTEST_TOBJ,0,FPC_EMPTYINTF
   DD   0,SYSTEM_TOBJECT_$__DESTROY,SYSTEM_TOBJECT_$__NEWINSTANCE$$TOBJECT,SYSTEM_TOBJECT_$__FREEINSTANCE
   DD   SYSTEM_TOBJECT_$__SAFECALLEXCEPTION$TOBJECT$POINTER$$LONGINT,SYSTEM_TOBJECT_$__DEFAULTHANDLER$formal
   DD   SYSTEM_TOBJECT_$__AFTERCONSTRUCTION,SYSTEM_TOBJECT_$__BEFOREDESTRUCTION,SYSTEM_TOBJECT_$__DEFAULTHANDLERSTR$formal
   DD   0
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   INITFINAL
INITFINAL   DD   3,0
   DD   INIT$_SYSTEM,0,INIT$_FPINTRES,0,INIT$_OBJPAS,FINALIZE$_OBJPAS
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   FPC_THREADVARTABLES
FPC_THREADVARTABLES   DD   1
   DD   THREADVARLIST_SYSTEM
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   FPC_RESOURCESTRINGTABLES
FPC_RESOURCESTRINGTABLES   DD   0
_DATA      ENDS

_      SEGMENT   PARA PUBLIC USE32 ''
   ALIGN 16
      DB   "FPC 2.3.1 [2009/07/01] for i386 - Win32"
_      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   __heapsize
__heapsize   DD   0
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   PUBLIC   __fpc_valgrind
__fpc_valgrind   DB   0
; End asmlist al_globals
; Begin asmlist al_const
; End asmlist al_const
; Begin asmlist al_typedconsts
; End asmlist al_typedconsts
; Begin asmlist al_rotypedconsts
; End asmlist al_rotypedconsts
; Begin asmlist al_threadvars
; End asmlist al_threadvars
; Begin asmlist al_imports
; End asmlist al_imports
; Begin asmlist al_exports
_DATA      ENDS

_CODE      SEGMENT   PARA PUBLIC USE32 'CODE'
; End asmlist al_exports
; Begin asmlist al_resources
; End asmlist al_resources
; Begin asmlist al_rtti
_CODE      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   INIT_P$FPTEST_IINTF
INIT_P$FPTEST_IINTF   DB   14,5
      DB   "iintf"
   DD   4
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
_$FPTEST$_Ld2   DW   0
   DD   _$FPTEST$_Ld3
   ALIGN 4
_$FPTEST$_Ld3   DW   0
_DATA      ENDS

_DATA      SEGMENT   PARA PUBLIC USE32 'DATA'
   ALIGN 4
   PUBLIC   INIT_P$FPTEST_TOBJ
INIT_P$FPTEST_TOBJ   DB   15,4
      DB   "tobj"
   DD   4,1,INIT_P$FPTEST_IINTF,4
; End asmlist al_rtti
; Begin asmlist al_dwarf_frame
; End asmlist al_dwarf_frame
; Begin asmlist al_dwarf_info
; End asmlist al_dwarf_info
; Begin asmlist al_dwarf_abbrev
; End asmlist al_dwarf_abbrev
; Begin asmlist al_dwarf_line
; End asmlist al_dwarf_line
; Begin asmlist al_picdata
; End asmlist al_picdata
; Begin asmlist al_resourcestrings
; End asmlist al_resourcestrings
; Begin asmlist al_objc_data
; End asmlist al_objc_data
; Begin asmlist al_end
; End asmlist al_end
_DATA      ENDS
   END


Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Различия между Delphi и FPC

Сообщение Max Rusov » 02.07.2009 15:56:35

Похоже, что в Вашей версии FPC еще не включен этот патч: http://bugs.freepascal.org/view.php?id=14019

Обратите внимание на код:

Код: Выделить всё
          lea   edx,dword ptr [ebp-48]
          mov   eax,ebx
          mov   ecx,ebx
          mov   ecx,dword ptr [ecx]
          call   dword ptr [ecx+12]        // Результат GetIntf пишется в temp [ebp-48]
          mov   ebx,dword ptr [ebp-48]
          lea   eax,dword ptr [ebp-48]
          call   FPC_INTF_DECR_REF
          mov   dword ptr [ebp-48],0       // Temp decref'ится, объект уничтожается
          lea   edx,dword ptr [ebp-48]
          mov   eax,ebx
          mov   ecx,ebx
          mov   ecx,dword ptr [ecx]
          call   dword ptr [ecx+12]       // Новый Getinf вызывается на уже уничтоженом объекте


Поэтому, видимо, у Вас и не наблюдается тот оверхеад, на который я сетовал. Вместо этого у Вас должна наблюдаться ошибка, которую я описал в первом посте.

Возможно Вы скачали исходники до 21.06 ?

Добавлено спустя 20 минут 15 секунд:
Sergei I. Gorelkin писал(а):Здесь-то понятно, в конструкции test2 временная переменная нужна, потому что интерфейс возвращается функцией. Нужно заметить, что в данном случае except-фрейм формируется и в Дельфи, причем Дельфи финализирует две переменные, а не одну, как FPC. Просто в Дельфи это выглядит несколько компактнее.


Это все понятно. Второй test я включил только для того, чтобы проверить, применен ли у Вас патч.
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение Sergei I. Gorelkin » 02.07.2009 16:34:21

Исходники я обновил из SVN вчера. Но... эта уродская TortoiseSVN по каким-то ей одной ведомым причинам не обновила часть файлов! :evil: :evil: :evil:
То есть информацию о ревизии файла она обновила, а содержимое - нет.
Придется еще раз все пересобирать нафиг.

Добавлено спустя 10 часов 21 минуту 52 секунды:
Кажется, в конце концов взаимопонимание было достигнуто... Поскольку создание ненужных интерфейсов действительно имеет место, я написал об этом в багтрекер: http://bugs.freepascal.org/view.php?id=14092 Пускай фиксят дальше.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Различия между Delphi и FPC

Сообщение Max Rusov » 08.07.2009 12:46:48

Еще один косяк, из разряда "несовместимо с жизнью" - не работает обработка системных исключений, если они возникли в DLL. Вообще. Программа тут-же слетает нафиг. :(

В коде замечательный коментарий:

{ install the handlers for exe only ?
or should we install them for DLL also ? (PM) }


Таки да, надо и для DLL! :evil:
Max Rusov
постоялец
 
Сообщения: 191
Зарегистрирован: 25.04.2009 15:46:03

Re: Различия между Delphi и FPC

Сообщение Sergei I. Gorelkin » 08.07.2009 13:33:27

Если установить системный обработчик в dll, то перестанут работать исключения в exe, потому что обработчик этот - один на процесс.
Там проблема несколько другая... Исключение, кинутое в dll, не попадает в обработчик exe, и как это исправить, чтобы работало кроссплатформенно - не слишком-то понятно.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1405
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

След.

Вернуться в IDE, компилятор, отладчик

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1

Рейтинг@Mail.ru