运行时检查失败 #2 - 变量“索引”周围的堆栈已损坏

Posted

技术标签:

【中文标题】运行时检查失败 #2 - 变量“索引”周围的堆栈已损坏【英文标题】:Run-Time Check Failure #2 - Stack around the variable 'indices' was corrupted 【发布时间】:2010-05-01 23:47:51 【问题描述】:

好吧,我想我知道问题出在哪里。我只是很难调试它。我正在使用directx api,我正在尝试根据我拥有的一本书沿x 和z 轴生成一个平面。问题是当我创建索引时。我想我设置的值超出了索引数组的范围。我只是很难弄清楚我做错了什么。我不熟悉这种生成平面的方法。所以对我来说有点困难。下面是我的代码。强调索引循环。

[编辑] 我一直在审查它。这就是索引的工作原理

 int curVertex = x + (z * NUM_VERTSX);

这总是得到开始的顶点。假设我们在 x 轴上有 17 个顶点,在 z 轴上有 17 个顶点,我们在 x 和 z 轴的第一个循环上

curVertx = 0 + (0 * 17) curVertx = 0 + 0 = 0

假设我们在 z 轴的第一个循环和 x 轴的第二个循环

curVertx = 1 + (0 * 17) curVertx = 1+ 0 = 1

indices[curIndex] = curVertex;
            indices[curIndex + 1] = curVertex + NUM_VERTSX;
            indices[curIndex + 2] = curVertex + 1;

            indices[curIndex + 3] = curVertex + 1;
            indices[curIndex + 4] = curVertex + NUM_VERTSX;
            indices[curIndex + 5] = curVertex + NUM_VERTSX + 1;

如果我们在第一个

loop indices[curIndex] = curVertex;

这等于第一个顶点 = 0。

indices[curIndex + 1] = curVertex + NUM_VERTSX;

这等于第二行顶点(它总是低于起始顶点的顶点

x x x x

[x] x x x

#include "MyGame.h"
//#include "CubeVector.h"
/* This code sets a projection and shows a turning cube. What has been added is the project, rotation and
a rasterizer to change the rasterization of the cube. The issue that was going on was something with the effect file
which was causing the vertices not to be rendered correctly.*/
typedef struct 

    ID3D10Effect* pEffect;
    ID3D10EffectTechnique* pTechnique;

    //vertex information
    ID3D10Buffer* pVertexBuffer;
    ID3D10Buffer* pIndicesBuffer;
    ID3D10InputLayout* pVertexLayout;

    UINT numVertices;
    UINT numIndices;
ModelObject;

ModelObject modelObject;
// World Matrix
D3DXMATRIX                  WorldMatrix;
// View Matrix
D3DXMATRIX                  ViewMatrix;
// Projection Matrix
D3DXMATRIX                  ProjectionMatrix;
ID3D10EffectMatrixVariable* pProjectionMatrixVariable = NULL;

//grid information
#define NUM_COLS 16
#define NUM_ROWS 16

#define CELL_WIDTH 32
#define CELL_HEIGHT 32

#define NUM_VERTSX (NUM_COLS + 1)
#define NUM_VERTSY (NUM_ROWS + 1)




bool MyGame::InitDirect3D()

    if(!DX3dApp::InitDirect3D())
    
        return false;
    

    D3D10_RASTERIZER_DESC rastDesc;
    rastDesc.FillMode = D3D10_FILL_WIREFRAME;
    rastDesc.CullMode = D3D10_CULL_FRONT;
    rastDesc.FrontCounterClockwise = true;
    rastDesc.DepthBias = false;
    rastDesc.DepthBiasClamp = 0;
    rastDesc.SlopeScaledDepthBias = 0;
    rastDesc.DepthClipEnable = false;
    rastDesc.ScissorEnable = false;
    rastDesc.MultisampleEnable = false;
    rastDesc.AntialiasedLineEnable = false;

    ID3D10RasterizerState *g_pRasterizerState;
    mpD3DDevice->CreateRasterizerState(&rastDesc, &g_pRasterizerState);
    mpD3DDevice->RSSetState(g_pRasterizerState);

    // Set up the World Matrix
    D3DXMatrixIdentity(&WorldMatrix);
    D3DXMatrixLookAtLH(&ViewMatrix, new D3DXVECTOR3(0.0f, 10.0f, -20.0f), new D3DXVECTOR3(0.0f, 0.0f, 0.0f), new D3DXVECTOR3(0.0f, 1.0f, 0.0f));
    // Set up the projection matrix
    D3DXMatrixPerspectiveFovLH(&ProjectionMatrix, (float)D3DX_PI * 0.5f, (float)mWidth/(float)mHeight, 0.1f, 100.0f);

    if(!CreateObject())
    
        return false;
    

    return true;


//These are actions that take place after the clearing of the buffer and before the present
void MyGame::GameDraw()


    static float rotationAngle = 0.0f;

    // create the rotation matrix using the rotation angle
    D3DXMatrixRotationY(&WorldMatrix, rotationAngle);
    rotationAngle += (float)D3DX_PI * 0.0f;

    // Set the input layout
    mpD3DDevice->IASetInputLayout(modelObject.pVertexLayout);

    // Set vertex buffer
    UINT stride = sizeof(VertexPos);
    UINT offset = 0;
    mpD3DDevice->IASetVertexBuffers(0, 1, &modelObject.pVertexBuffer, &stride, &offset);
    mpD3DDevice->IASetIndexBuffer(modelObject.pIndicesBuffer, DXGI_FORMAT_R32_UINT, 0);

    // Set primitive topology
    mpD3DDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

    // Combine and send the final matrix to the shader
    D3DXMATRIX finalMatrix = (WorldMatrix * ViewMatrix * ProjectionMatrix);
    pProjectionMatrixVariable->SetMatrix((float*)&finalMatrix);


    // make sure modelObject is valid


    // Render a model object
    D3D10_TECHNIQUE_DESC techniqueDescription;
    modelObject.pTechnique->GetDesc(&techniqueDescription);

    // Loop through the technique passes
    for(UINT p=0; p < techniqueDescription.Passes; ++p)
    
        modelObject.pTechnique->GetPassByIndex(p)->Apply(0);

        // draw the cube using all 36 vertices and 12 triangles
        mpD3DDevice->DrawIndexed(modelObject.numIndices,0,0);
    


//Render actually incapsulates Gamedraw, so you can call data before you actually clear the buffer or after you 
//present data
void MyGame::Render()

    DX3dApp::Render();


bool MyGame::CreateObject()

    VertexPos vertices[NUM_VERTSX * NUM_VERTSY];
    for(int z=0; z < NUM_VERTSY; ++z)
    
        for(int x = 0; x < NUM_VERTSX; ++x)
        
            vertices[x + z * NUM_VERTSX].pos.x = (float)x * CELL_WIDTH;
            vertices[x + z * NUM_VERTSX].pos.z = (float)z * CELL_HEIGHT;

            vertices[x + z * NUM_VERTSX].pos.y = 0.0f;

            vertices[x + z * NUM_VERTSX].color = D3DXVECTOR4(1.0, 0.0f, 0.0f, 0.0f);
        
    

    DWORD indices[NUM_VERTSX * NUM_VERTSY];
    int curIndex = 0;

    for(int z=0; z < NUM_ROWS; ++z)
    
        for(int x = 0; x < NUM_COLS; ++x)
        
            int curVertex = x + (z * NUM_VERTSX);
            indices[curIndex] = curVertex;
            indices[curIndex + 1] = curVertex + NUM_VERTSX;
            indices[curIndex + 2] = curVertex + 1;

            indices[curIndex + 3] = curVertex + 1;
            indices[curIndex + 4] = curVertex + NUM_VERTSX;
            indices[curIndex + 5] = curVertex + NUM_VERTSX + 1;

            curIndex += 6;
        
    



    //Create Layout
    D3D10_INPUT_ELEMENT_DESC layout[] = 
        "POSITION",0,DXGI_FORMAT_R32G32B32_FLOAT, 0 , 0, D3D10_INPUT_PER_VERTEX_DATA, 0,
        "COLOR",0,DXGI_FORMAT_R32G32B32A32_FLOAT, 0 , 12, D3D10_INPUT_PER_VERTEX_DATA, 0
    ;

    UINT numElements = (sizeof(layout)/sizeof(layout[0]));
    modelObject.numVertices = sizeof(vertices)/sizeof(VertexPos);

    //Create buffer desc
    D3D10_BUFFER_DESC bufferDesc;
    bufferDesc.Usage = D3D10_USAGE_DEFAULT;
    bufferDesc.ByteWidth = sizeof(VertexPos) * modelObject.numVertices;
    bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
    bufferDesc.CPUAccessFlags = 0;
    bufferDesc.MiscFlags = 0;

    D3D10_SUBRESOURCE_DATA initData;
    initData.pSysMem = vertices;
    //Create the buffer

    HRESULT hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &modelObject.pVertexBuffer);
    if(FAILED(hr))
        return false;

    modelObject.numIndices = sizeof(indices)/sizeof(DWORD);

    bufferDesc.ByteWidth = sizeof(DWORD) * modelObject.numIndices;
    bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;

    initData.pSysMem = indices;

    hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &modelObject.pIndicesBuffer);
    if(FAILED(hr))
        return false;


    /////////////////////////////////////////////////////////////////////////////
    //Set up fx files
    LPCWSTR effectFilename = L"effect.fx";
    modelObject.pEffect = NULL;

     hr = D3DX10CreateEffectFromFile(effectFilename,
        NULL,
        NULL,
        "fx_4_0",
        D3D10_SHADER_ENABLE_STRICTNESS,
        0,
        mpD3DDevice,
        NULL,
        NULL,
        &modelObject.pEffect,
        NULL,
        NULL);

    if(FAILED(hr))
        return false;

    pProjectionMatrixVariable = modelObject.pEffect->GetVariableByName("Projection")->AsMatrix();
    //Dont sweat the technique. Get it!
    LPCSTR effectTechniqueName = "Render";

    modelObject.pTechnique = modelObject.pEffect->GetTechniqueByName(effectTechniqueName);
    if(modelObject.pTechnique == NULL)
        return false;


    //Create Vertex layout
    D3D10_PASS_DESC passDesc;
    modelObject.pTechnique->GetPassByIndex(0)->GetDesc(&passDesc);

    hr = mpD3DDevice->CreateInputLayout(layout, numElements,
        passDesc.pIAInputSignature,
        passDesc.IAInputSignatureSize,
        &modelObject.pVertexLayout);
    if(FAILED(hr))
        return false;

    return true;

【问题讨论】:

【参考方案1】:

您的 indices 数组每个“单元格”包含 6 个条目(因为您要为每个单元格绘制两个三角形),因此应将其声明为

DWORD indices[NUM_ROWS * NUM_COLS * 6]

你得到的错误告诉你,你写在indices的边界之外,这通常是一个错误声明的提示(或错误的索引计算)。

【讨论】:

你是对的。书上也是这么说的。看起来通过了它【参考方案2】:

现在让我们看看有问题的代码 sn-p(可能的根本原因)

代码

 DWORD indices[NUM_VERTSX * NUM_VERTSY];
int curIndex = 0;

for(int z=0; z < NUM_ROWS; ++z)

    for(int x = 0; x < NUM_COLS; ++x)
    
        int curVertex = x + (z * NUM_VERTSX);
        indices[curIndex] = curVertex;
        indices[curIndex + 1] = curVertex + NUM_VERTSX;
        indices[curIndex + 2] = curVertex + 1;

        indices[curIndex + 3] = curVertex + 1;
        indices[curIndex + 4] = curVertex + NUM_VERTSX;
        indices[curIndex + 5] = curVertex + NUM_VERTSX + 1;

        curIndex += 6;
    

分析

    这里索引的最大“单元”数 = NUM​​_VERTX * NUM_VERTSY = (16 + 1) * (16+1) = 289。所以有 0...288 个“单元”。在边界条件期间 - z = 15,x = 15 的值。所以 curIndex 将是 15 * 15 * 6 = 1350。这远远超过了分配的单元格。

建议

    由于三个值决定了目标数组的大小,所以这三个值都必须是数组分配的一部分。因此,如果您使用 DWORD 索引[NUM_VERTSX * NUM_VERTSY * UNIT_BLOCK],其中 UNIT_BLOCK = 6,它应该可以正常工作。

    除了在代码中嵌入幻数之外,您还可以使用 const 变量 - 以后会有很大帮助(如果您想更改索引的值)。

HTH

【讨论】:

感谢您的回复,当我有机会回顾我的代码时,我会告诉你们结果。 实际上 curIndex 将是 15 + ( 15 * 6) = 105。我不确定我是否正确查看。如果我错了,请纠正我。

以上是关于运行时检查失败 #2 - 变量“索引”周围的堆栈已损坏的主要内容,如果未能解决你的问题,请参考以下文章

c++ 运行时检查失败 #2 - 变量“ToSend22”周围的堆栈已损坏

运行时检查失败 #2 - 变量周围的堆栈已损坏

运行时检查失败 #2 - 变量“primes”周围的堆栈已损坏

运行时检查失败 #2 - 变量“l1”周围的堆栈已损坏

运行时检查失败 #2 - 变量“cid1”周围的堆栈已损坏

运行时检查失败 #2 - 变量“e_color”周围的堆栈已损坏