RAD Studio 10.1 Berlin clang Probleme durch Optimierung im Release-Build
-
Hallo,
ich habe Problem mit dem clang Compiler im Release Build. Es sieht so aus, als würde er Funktionsaufrufe wegoptimieren und dadurch habe ich ein falsches Verhalten in meinem Formular. Im Event Handler einer Action habe ich zum Entprellen der Action einen lokalen Guard, der den
Enabled
Status für den Scope des Event Handlers auffalse
setzt. Beim Verlassen des Scopes wird derEnabled
Status auf den ursprünglichen Wert zurückgesetzt. Im Debug Modus funktioniert das, im Release Modus allerdings nicht. Konkret habe ich einenTButton
im Speedbutton-Modus, an dem eineTAction
hängt. DerDown
-Status des Speedbutton hängt also vomChecked
-Status der Action ab. Unabhängig vom ursprünglichen Status wechselt derDown
-Status immer nachfalse
und springt nicht um. Dieses Verhalten tritt nur mit dem clang Compiler und nur im Release Build auf.namespace { template<typename T> T* set_state( TObject* Sender, bool State, bool* SaveState = NULL ) { T* ptr = dynamic_cast<T*>( Sender ); if( ptr ) { if( SaveState ) *SaveState = ptr->Enabled; ptr->Enabled = State; } return ptr; } } class ScopedVCLDebounceGuard { bool SaveState_; TObject* Control_; public: ScopedVCLDebounceGuard( TObject* Sender ) : SaveState_( false ), Control_( Sender ) { if( !set_state<TControl>( Control_, false, &SaveState_ ) ) { set_state<TAction>( Control_, false, &SaveState_ ); } } ~ScopedVCLDebounceGuard() { if( !set_state<TControl>( Control_, SaveState_ ) ) { set_state<TAction>( Control_, SaveState_ ); } } private: ScopedVCLDebounceGuard( const ScopedVCLDebounceGuard& ); ScopedVCLDebounceGuard& operator=( const ScopedVCLDebounceGuard& ); }; __fastcall TForm1::TForm1( TComponent* Owner ) : TForm(Owner) { } bool TForm1::checked() const { return ActionTest->Checked; } void TForm1::set_checked( bool Checked ) { ActionTest->Checked = Checked; } void __fastcall TForm1::OnActionTest( TObject* Sender ) { ScopedVCLDebounceGuard Lock( Sender ); set_checked( !checked() ); }
Hat jemand eine Idee, wie man das löst? Ich benutze das an einigen hundert Stellen in unserem Code und möchte das nicht in jedem Event Handler einzeln fixen müssen.
-
Edit:
Es scheint wohl amTcxButton
zu liegen. Ich habe das Verhalten mit einemTSpeedButton
getestet und mit dem geht´s.
-
Und mit dieser Version des DebounceGuards geht´s auch im Release Modus:
template<typename ObjType> class ScopedVCLDebounceGuard { bool SaveState_; ObjType* Control_; public: ScopedVCLDebounceGuard( TObject* Sender ) : SaveState_( false ), Control_( dynamic_cast<ObjType*>( Sender ) ) { if( Control_ ) { SaveState_ = Control_->Enabled; Control_->Enabled = false; } } ~ScopedVCLDebounceGuard() { if( Control_ ) { Control_->Enabled = SaveState_; } } private: ScopedVCLDebounceGuard( const ScopedVCLDebounceGuard& ); ScopedVCLDebounceGuard& operator=( const ScopedVCLDebounceGuard& ); };
Ich versteh´s mal grad so überhaupt nicht
-
Hab das jetzt mit dem clang vom 10.2 Tokyo probiert, damit macht der Code genau das, was er soll. War wohl ein Bug im Compiler, die Version 3.3.6408.36116 macht´s richtig.
-
Hallo,
also deine zweite Version ist schon mal viel besser als die erste, allerdings ist da auch immer noch zu viel
if
unddynamic_cast
drin.
Einfach so:template<typename ObjType> class ScopedVCLDebounceGuard { bool SaveState_; ObjType* Control_; public: ScopedVCLDebounceGuard( ObjType* Sender ) : SaveState_( Sender->Enabled ), Control_( Sender ) { Control_->Enabled = false; } ~ScopedVCLDebounceGuard() { Control_->Enabled = SaveState_; } };
Die Frage, wieso das in 10.2 geht aber mit 10.1 nicht, interessiert mich allerdings auch mehr.
Einen Fehler sehe ich in der ersten Version auch nicht. Sicher, dass es nicht vielleicht mit diesem TcxButton zu tun hat?Kennst du zufällig eine Seite wo mal die konkrekten Features/Änderungen zw. den clang-Compiler-Versionen 10.1 -> 10.2 beschrieben wird?
Ich teste gerade die 10.2 und die IDE stürzt bei mir doch sehr häufig mit Speicherzugriffsfehlern ab. Meine vorherigen Tests mit 10.1 waren nicht so schlimm, deshalb spiele ich mit dem Gedanken auf die 10.1 zu gehen. Solche Posts wie Deiner hier, machen mir jetzt etwas Angst...
Wie ist es mit der 10.2er (IDE)-Stabilität bei Dir?
-
OK, deine erste Version ist doch falsch. Der set_state-Aufruf im Destruktor passt gar nicht und der Compiler hätte sich beschweren müssen.
Oder hast du da noch eine anderes set_state() rumliegen?
-
Warum ist die falsch?
-
zu wenig argumente, bool statt &bool.
T* set_state( TObject* Sender, bool State, bool* SaveState = NULL ); ~ScopedVCLDebounceGuard() { if( !set_state<TControl>( Control_, SaveState_ ) ) { set_state<TAction>( Control_, SaveState_ ); } }
das sowas ohne Fehler mit dem bcc kompiliert bin ich gewohnt. Wenn das beim clang-Compiler immer noch so ist, wäre ich mehr enttäuscht, als ich mir hätte vorstellen können.
-
Ich sehe in dem Code auch keinen Fehler (SaveState_ wird als 2. Parameter übergeben und der dritte Parameter ist optional, also wird der Defaultwert NULL benutzt).
-
ups hast recht