GetCPUDescriptorHandleForHeapStart-Stapelbeschädigung

9

Ich bin anscheinend auf ein Problem gestoßen, das die Programmierung von DirectX 12.0 betrifft, und bisher gab es keine Forschungsergebnisse, die einen Einblick in das Problem boten. Daher musste ich das Problem selbst lokalisieren, außer dass es noch keine greifbare Lösung zu geben scheint.

Um Sie zu informieren, ich programmiere mit C (nicht C ++) und, wie offensichtlich ist, unterstützen die DirectX 12-Header-Dateien tun C neben C ++, obwohl das Problem, das ich angetroffen habe seltsam ist insofern scheint es schlecht für C entworfen zu sein, wahrscheinlich aufgrund der Tatsache, dass nicht viele Leute komplexe (insbesondere objektorientierte) Anwendungen in dieser Sprache programmieren.

Das ist mein Problem: Ich habe hier in meinem D3D12-Gerät-Initialisierungsprozedur den folgenden Code-Block:

%Vor%

Wo hRTV steht für Handle für Render-Zielansicht '(D3D12_CPU_DESCRIPTOR_HANDLE) und pRTVHeap steht für' Zeiger auf Zielansichts-Heap rendern '(ID3D12DescriptorHeap).

Hier ist das C ++ - Äquivalent - das funktioniert gut:

%Vor%

Es sind keine Kompilierungsfehler vorhanden, aber zur Laufzeit löst das Aufrufen dieser Methode (GetCPUDescriptorHandleForHeapStart) in C eine Stapelkorruption aus (ESP wird um 4 Byte falsch ausgerichtet).

Ich habe die Disassemblierung für die Methode untersucht und die Anweisung RET (Return) zur Kenntnis genommen:

%Vor%

Für diejenigen, die mit Assembly vertraut sind, oder sonst die __stdcall-Aufrufkonvention von COM (Component Object Model) -Objekten, ist der auf dem Stack übergebene "this" -Zeiger der erste Parameter (und in diesem Fall auch der einzige) Parameter) der Methode, damit das COM-Objekt auf seine eigenen Daten zugreifen kann.

Das folgende Code-Snippet (auch am Ende des Code-Snippets oben gezeigt) ruft meine Verwirrung auf, und zwar zu Recht, wenn die Laufzeitumgebung einen "fehlausgerichteten ESP" -Fehler verursacht:

%Vor%

In diesem Fall wird nur ein Parameter übergeben, der der 'Dies'-Zeiger ist. Die Größe eines Zeigers (auf einem 32-Bit-System - meine Zielarchitektur ist im Moment x86) beträgt 4 Bytes (32 Bits). Warum räumt der Aufgerufene also 8 Bytes auf dem Stapel auf?

Habe ich Recht, dies einen Fehler zu nennen? Muss Microsoft über dieses Problem informiert werden? Liege ich falsch? Ist das ein dummer Fehler meinerseits?

Vielen Dank für Ihre Zeit und ich hoffe, dass jemand mit mehr Wissen als ich über das Thema aufklären kann, aber schlagen Sie bitte nicht vor, dass die Lösung wäre, in C ++ anstatt C zu schreiben. Ich habe das bereits berücksichtigt und festgestellt es sollte nicht notwendig sein und ich persönlich empfinde in meinem Fall, dass dies ein fauler Lösungsansatz wäre, besonders wenn ich finde, dass C mehr programmatische Kontrolle und (in meinem Fall hier) mehr Effizienz ermöglicht.

    
Cara Ames 06.12.2015, 15:11
quelle

1 Antwort

4

LÖSUNG

Ich habe mein eigenes Problem behoben. Nach dem Laden von Debug-Symbolen für D3D12.DLL konnte ich anhand der Namenskonventionen (z. B. ID3D12DescriptionHeap :: GetCPUDescriptorHandleForHeapStart, doppelte Doppelpunkte sind hier indikativ) feststellen, dass die DLL in C ++ geschrieben wurde. Ein (versteckter) zweiter Parameter wird tatsächlich an die Funktion übergeben - ein Zeiger auf die Ausgabestruktur, die als D3D12_CPU_DESCRIPTOR_HANDLE definiert ist (was strukturell nur eine ganze Zahl ist, Aliasing als Struktur. Ich weiß nicht, warum sie das tun). Ich habe vergessen, dass C ++ sich von C dadurch unterscheidet, dass C ++ Strukturen als Rückgabewerte zurückgeben kann und dass Strukturen nicht als Rückgabe über das EAX-Register übergeben werden können, so dass es als Zeiger auf dem Stack an den Aufgerufenen übergeben werden muss.

Microsoft sollte dies dokumentieren !! Kein Fehler, nur schlechte Dokumentation! Die Header-Datei spezifiziert (in der C-definierten Schnittstellenmethode) diesen Unterschied nicht!

%Vor%

Sollte sein:

%Vor%

Microsoft muss das aussortieren.

    
Cara Ames 16.12.2015, 21:58
quelle

Tags und Links