当前位置:  开发笔记 > 编程语言 > 正文

GetCPUDescriptorHandleForHeapStart堆栈损坏

如何解决《GetCPUDescriptorHandleForHeapStart堆栈损坏》经验,为你挑选了1个好方法。

我似乎偶然发现了有关DirectX 12.0编程的问题,到目前为止还没有研究能够深入了解这个问题.因此,除了似乎还没有一个切实可行的解决方案之外,我一直在寻找问题.

要告诉你,我现在用C(不是C++)和编程,因为很明显,提供了DirectX 12头文件支持C,沿着C++,虽然我已经遇到的问题是奇怪的,因为它似乎是设计不良的C,可能由于没有多少人用这种语言编写复杂的(特别是面向对象的)应用程序.

这是我的问题:我在D3D12设备初始化过程中有以下代码块:

/* Get a handle to the memory location in the render target
view heap to identify where the render target views will be
located for the two back buffers */
hRTV = pThis->pRTVHeap->lpVtbl->GetCPUDescriptorHandleForHeapStart(pThis->pRTVHeap);

HRTV代表" 处理,以渲染目标视图 "(D3D12_CPU_DESCRIPTOR_HANDLE)和pRTVHeap代表" 指针渲染目标视图堆 "(ID3D12DescriptorHeap).

这是C++的等价物 - 这很好用:

/* Get a handle to the memory location in the render target
view heap to identify where the render target views will be
located for the two back buffers */
hRTV = this->pRTVHeap->GetCPUDescriptorHandleForHeapStart();

没有编译时错误,但在运行时,在C中调用此方法(GetCPUDescriptorHandleForHeapStart)会触发堆栈损坏(ESP变为4字节错位).

我检查了方法的反汇编并记下了RET(返回)指令:

mov         edi,edi
push        ebp
mov         ebp,esp
mov         ecx,dword ptr [ebp+8]
mov         eax,dword ptr [ecx+2Ch]
cmp         dword ptr [eax],2
jne         5029004A
mov         eax,dword ptr [ebp+0Ch]
mov         ecx,dword ptr [ecx+28h]
mov         dword ptr [eax],ecx
jmp         50290055
push        dword ptr [ebp+0Ch]
call        5029005E
mov         eax,dword ptr [ebp+0Ch]
pop         ebp
ret         8

对于那些熟悉汇编或者COM(组件对象模型)对象的__stdcall调用约定的人来说,在堆栈上传递的'this'指针是第一个参数(在这种情况下,也是唯一的参数)该方法使COM对象可以访问自己的数据.

下面的代码片段(也显示在上面代码片段的末尾)调用了我的混淆,理所当然,当运行时抛出'错位的ESP'错误时:

ret        8

在这种情况下,只传递一个参数,即'this'指针.指针的大小(在32位系统上 - 我目前的目标架构是x86)是4个字节(32位),那么为什么被调用者清理堆栈上的8个字节?

我称这是一个错误吗?Microsoft是否需要了解此问题?我错了吗?这对我来说是一个愚蠢的错误吗?

感谢您的时间,我希望知识比我更多的人可以在这个问题上给我启发,但请不要建议解决方案是用C++而不是C编写.我已经考虑过这个问题并得出结论认为它不应该在我的情况下,我认为这是一种懒惰的解决方法,特别是当我发现C允许更多的程序控制和(在我的情况下)更高效率时.



1> Cara Ames..:

D3D12.DLL的调试符号显示得足够。命名约定(例如ID3D12DescriptionHeap::GetCPUDescriptorHandleForHeapStart)强烈表明DLL是用C ++编写的。一个(隐藏的)第二个参数确实传递给该方法-指向输出结构的指针D3D12_CPU_DESCRIPTOR_HANDLE(仅包含一个整数,别名为结构。我不知道他们为什么这样做)。我忘记了C ++与C的不同之处在于C ++可以将结构作为返回值返回,并且不能通过累加器(%EAX)寄存器将结构作为返回传递,因此必须将其作为指针传递给堆栈上的被调用方。

问题是不良的C绑定(Microsoft标头错误)。建议采取以下修复措施:

旧代码:

D3D12_CPU_DESCRIPTOR_HANDLE (
    STDMETHODCALLTYPE *GetCPUDescriptorHandleForHeapStart )( 
    ID3D12DescriptorHeap * This);

用。。。来代替:

void ( STDMETHODCALLTYPE *GetCPUDescriptorHandleForHeapStart )(
    ID3D12DescriptorHeap *This, D3D12_CPU_DESCRIPTOR_HANDLE *pOut);

谢谢。

推荐阅读
mobiledu2402851203
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有