Baut mein Compiler mist beim Optimieren?



  • Huhu,

    mein Visual C++.net 2003 Compiler stellt mich vor eine ziemlich unverständliches Listing.

    Also, es geht um eine Soundausgabe mit der WinAPI Funktion waveOutWrite.
    Das Programm soll solange Idlen, bis eine Strukturvariable auf 1 gesetzt wird, wenn das Wave durch ist.

    #define WHDR_DONE 1;
    ...
    hResult = waveOutWrite(s_woDevice, &s_WaveHdr, sizeof(WAVEHDR)); 
    if (hResult != MMSYSERR_NOERROR)	return -1;
    
    while (!(s_WaveHdr.dwFlags & WHDR_DONE)) {/*Leerlauf*/};
    

    Soweit, so gut.
    Solange nicht optimiert wird, klappt alles.
    Aber wenn ich den Compiler optimieren lasse, wirds eine Endlosschleife.
    Das ASM-Listing der letzten Zeile:

    00149	8b 44 24 30	 mov	 eax, DWORD PTR _s_WaveHdr$[esp+80]
    0014d	83 e0 01	     and	 eax, 1
    $L75394:
    
    ; 67   : 		
    ; 68   : 		while (!(s_WaveHdr.dwFlags & WHDR_DONE)) {/*Leerlauf*/};
    
    00150	85 c0		 test	 eax, eax
    00152	74 fc		 je	 SHORT $L75394
    

    Der Ablauf, wie ich ihn verstehe:
    1. eax wird auf den Wert der Strukturvariable gesetzt.
    2. Nach dem and ist eax entweder 1 oder 0. Gehen wir mal von 0 aus.
    3. in Zeile 00150 wird jetzt ohne Registeränderung nochmal geprüft.
    4. Es folgt ein Jump, da eax natürlich eax entspricht. (ist equal)
    5. Es wird aber nur eine Zeile zurückgesprungen, ergo kann sich der Wert von eax gar nicht mehr ändern.
    Also ➡ Endlosschleife.

    So war das aber nicht gemeint.
    _DARF_ der das? 😡 Aus while (!(s_WaveHdr.dwFlags & WHDR_DONE)) machen?
    Oder seh ich was falsch? 😕



  • Dürfen eigentlich nicht, aber da ist VC++ recht agressiv. Ist auf jedenfall grauzone.

    die Lösung: deklariere deine variable als volatile. Damit darf er es nicht mehr wegoptimieren.



  • Hi,

    volatile hatte ich auch schon probiert, aber da müsste ich die ganzen Funktionensköpfe umschreiben, die die Struktur verwenden.

    Was die Sache noch wirrer macht: lege ich einen Sleep(500); Befehl vor das while, geht es. Obwohl das Asm-Listing so bleibt.

    Vielleicht ist es also doch eher eine Blockade der Windowsmessages.
    Aber Sleep blockiert doch eigentlich auch ...
    Ich schreibs gerade als Win32-App um. Vielleicht tut ers da ja.

    Trozdem versteh ich diese Optimierung nicht. 😮


  • Mod

    du kannst das volatile auch per cast an dieser stelle einfügen. die optimierung, die dort stattfindet ist logisch und auch statthaft. generell geht der compiler davon aus, dass sich ein wert nur ändert, wenn das programm es an der stelle, an der darauf zugegriffen wird, es selbst tut. deswegen gibt es ja das volatile schlüsselwort, für fälle, wo werte durch externe prozesse verändert werden.



  • Alles klar,
    mit volatile läuft es wunderbar 👍

    Merci 😋


Anmelden zum Antworten