Das hier verursacht einen Deadlock in XAudio2, der – falls ich Glück habe – nach zehn Minuten mit einer Zugriffsverletzung endet. Zwei Internets für den, der mir sagen kann, was ich falsch mache. Bin scheinbar seit Tagen im Wald-vor-lauter-Bäumen-Modus.
CoInitializeEx(nullptr, COINIT_MULTITHREADED);
IXAudio2 * audio = nullptr;
XAudio2Create(&audio);
IXAudio2MasteringVoice * voice;
audio->CreateMasteringVoice(&voice);
// Hier scheint alles bestens; ich könnte sogar schön Source Voices erzeugen und damit Sounds abspielen, unterbrechen und blablah
voice->DestroyVoice(); // DEADLOCK
Falls ich im Debug-Modus arbeite, gibt es keine Meldungen außer
Unloaded 'C:\Windows\SysWOW64\avrt.dll'
The thread 'Win32 Thread' (0x1018) has exited with code 0 (0x0).
Die Zeit, die XAudio2 zum Zerstören der Mastering Voice braucht, ist linear abhängig von der Menge reservierten Stapelspeichers. Wenn ich 1 GiB reserviere (/STACK:1073741824; die Einstellung hatte ich noch als Überbleibsel von meinen _alloca()-Experimenten), dauert die Zerstörung halt zehn Minuten. Bei einem MiB ist es kaum mehr spürbar.
Dieser Stapelspeicher ist zwar reserviert, wird aber zu keiner Zeit genutzt. Darum in aller Deutlichkeit:
WTF?!?
Mir ist klar, dass XAudio2 einen Thread für meine Mastering Voice erstellt, und der mit aller Wahrscheinlichkeit genauso viel Stapel zugesichert bekommt. Aber der wird ja auch nicht benutzt, sonst würde das im Task-Manager auftauchen. Warum beschäftigt sowas minutenlang WaitForSingleObject()? Was zur …?!?
Und das nur beim Runterfahren, vorher alles ruck-zuck?
Werden Seiten eigentlich beim Lesen comitted? Falls nicht, haben die bestimmt irgendeinen Debugging-Scheiß in der DLL vergessen und suchen den kompletten Stapel einmal von oben nach unten nach Magic Numbers ab oder so … Copy on Write?
Keine Datenträgeraktivität, keine CPU-Auslastung, keine Seitenfehler, nichts. Er hängt einfach nur in WaitForSingleObject() irgendwo in den Annalen von XAudio2.
Ich muss auch das „linear“ zurücknehmen. Bis kurz vor 1 GB merkt man quasi nichts; bei 900.000.000 B sind es 2 s; bei 1.000.000.000 B schon 8 s; bei 1.073.741.824 zehn Minuten und 1.200.000.000 habe ich eben abgebrochen.
Es nervt auch, dass Visual C++ nach Ändern des Werts nicht neu linken will. Ich muss immer Rebuild’en, damit er übernommen wird …
Was habe ich nur wieder für ein Glück. Die absolut unscheinbarste Linker-Einstellung lässt einen API-Aufruf länger dauern, und auch nur, weil ich in einer Mixtur aus Zufall und Wahn eine Zahl der richtigen Größenordnung getroffen habe. Derweil funktionierte mein Programmtext, den ich die letzten vier Tage bis ins letzte Byte gedebuggt habe, natürlich seit jeher fehlerfrei.