Перейти к содержанию
Fire Monkey от А до Я

UniSoft

Пользователи
  • Постов

    2
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные UniSoft

  1. ну исходники библиотек то одни...

    а вот в x64 не проявляется...

    да и еще этот баг там не единственный, понизив приоритет инициализатора все запускается нормально,

    но падает уже при закрытии и в каком-то другом модуле.

     

    патч fmx.lib и cw32mt.lib решают проблему... 

    http://rghost.net/6rNpG5LlC 

    но я бы не рекомендовал это использовать, высока вероятность, 

    что может начать конфликтовать с какими либо другими модулями.

     

    как устроена инициализация, и о каких приоритетах идет речь, 
    можно посмотреть тут: функция _init_exit_proc() 
    C:\Program Files (x86)\Embarcadero\Studio\16.0\source\cpprtl\Source\startup\initexit.c 
    C:\Program Files (x86)\Embarcadero\Studio\16.0\source\cpprtl\rtlinc\_startup.h 

     

    по хорошему, нужно бы отправить баг-репорт, ведь баг то критический,

    но у меня нет EDN аккаунта.

  2. Проблема в инициализации модулей, точнее в последовательности их инициализации.
     
    FMX.Types.pas
    initialization
        ...
        // <<< тут проблема, 
        // на момент вызова этого конструктора, инициализация модуля System.Rtti.pas
        // еще не выполнялась...
        // т.е. модуль System.Rtti.pas инициализируется после FMX.Types.pas
        SharedContext := TRttiContext.Create;
        ...
    
     
    System.Rtti.pas
    class function TRttiContext.Create: TRttiContext;
    begin
      EnsurePoolToken(@Result.FContextToken);
    end;
     
    constructor TPoolToken.Create;
    begin
      TMonitor.Enter(PoolLock); // вот тут то и падение, модуль еще не инициализирован и PoolLock = nil
      try
        if Pool = nil then
        begin
          Pool := TRttiPool.Create;
          PoolRefCount := 1;
        end
        else
          Inc(PoolRefCount);
      finally
        TMonitor.Exit(PoolLock);
      end;
    end;
     
    procedure EnsurePoolToken(TokenRef: PInterface);
    var
      sample: Pointer;
     
      procedure DoCreate;
      var
        tok: IInterface;
      begin
        tok := TRttiContext.FGlobalContextToken;
        if tok = nil then
          tok := TPoolToken.Create;
        if AtomicCmpExchange(PPointer(TokenRef)^, Pointer(tok), sample) = sample then
        begin
          // We won the race to initialize the TokenRef location, so
          // zero-out interface reference without decrementing reference count.
          PPointer(@tok)^ := nil;
        end;
      end;
     
    begin
      sample := PPointer(TokenRef)^;
      if sample <> nil then
        Exit;
      DoCreate;
    end;
     
    initialization
      ...
      PoolLock := TObject.Create;
    
     
    Есть еще один нюанс, инициализация System.Rtti.pas зачем-то выполняется два раза,
    к краху это не приведет, но небольшой (не накопительный) memleak будет.
     
    Проблема в библиотеках, и похоже только Win32
     
    ЗЫ. к стилям никакого отношения не имеет...
    достаточно одной строчки: 
    void __fastcall TForm1::FormCreate(TObject *Sender)
    {
        TValue::From<String>("test");
    }
    
×
×
  • Создать...