【问题标题】:C++ WINAPI Exception Unhandled Stack Overflow before reaching codeC++ WINAPI 异常未处理堆栈溢出之前到达代码
【发布时间】:2019-08-10 04:54:58
【问题描述】:

我在 Direct x 中组装了一个不错的小型地形引擎。我将土地的widthheight256 更改为512,现在当我运行调试器时,程序在wWinMain 中崩溃。 WidthHeightconst static unsigned int 我应该补充一点,如果我将数字改回 256,则程序可以正常调试而不会出错。只有在更改这些数字时才会引发堆栈溢出错误。

Unhandled exception at 0x00007FF7065C9FB8 in TerrainEngine.exe: 0xC00000FD: Stack overflow (parameters: 0x0000000000000001, 0x00000022AA803000).

class Constants
{
public:
    // World rows and columns
    const static unsigned int WorldWidth = 256; //changing this to a number greater than
    const static unsigned int WorldHeight = 256; //256 causes stack overflow

将 WorldWidth 或 WorldHeight 更改为大于 256 的数字时,我在代码的最开始出现堆栈溢出错误,太早了以至于我无法进一步正确调试以查看问题所在。

void World::Initialize(Graphics & graphics)
{
    this->graphics = &graphics;

    ....

    // Setup Perlin Noise
    PerlinNoise perlinNoise = PerlinNoise(237);

    for (unsigned int y = 0; y < Constants::WorldHeight; y++)
    {
        for (unsigned int x = 0; x < Constants::WorldWidth; x++)
        {
            double xx = (double)x / ((double)Constants::WorldWidth);
            double yy = (double)y / ((double)Constants::WorldHeight);

            //define in header as std::array<std::array<float, Constants::WorldWidth>, Constants::WorldHeight> heightmap;
            heightmap[x][y] = perlinNoise.noise(xx, yy, 1);
            tileManager.SetTile(x, y, Math::GetType(heightmap[x][y]));
        }
    }
}


void World::Update(Keyboard& keyboard)
{
    // The only other time WorldWidth is referenced
    //posX is public signed int
    posX = Math::Clamp(
        posX,
        Constants::WorldWidth - Constants::RenderWidth,
        Constants::RenderWidth);

谁能解释发生了什么,因为我无法调试导致 wWinMain 方法的第一个花括号,而且我不明白更改这两个值如何导致程序抛出此错误。

World 在 Game 头文件中被声明为原始的、普通的私有成员。

World world;

它有一个为空的构造函数。

【问题讨论】:

  • 当值大于 256 时,我无法调试它,否则编译器不会走那么远。否则,似乎没有什么不寻常的。我知道构造函数接受宽度和高度并使用它们来声明一个指针到指针的数组。
  • std::cout &lt;&lt; sizeof( MainWindow ) &lt;&lt; sizeof( Game ) &lt;&lt; "\n"; 有告诉你什么吗?如果它没有按原样运行,您可以注释掉这两个 try 块。
  • 失败时的堆栈跟踪是什么?可能你在全局变量初始化中有无限递归。
  • 显示创建World 实例的代码。如果你把它创建到堆栈上你有问题,堆栈的大小是有限的,windows 上的默认值是 1MB,所以512*512*sizeof(float) 给你 1 MB。因此堆栈溢出。通过new在堆上创建World

标签: c++ winapi memory directx stack-overflow


【解决方案1】:

您有一个非常大的数组,它目前是编译器放置在堆栈上的具有自动生命周期的变量的一部分。由于它太大而无法容纳,因此会出现堆栈溢出。

替换声明为的数组

double heightmap[Constants::WorldWidth][Constants::WorldHeight];

通过

std::unique_ptr<double [][Constants::WorldHeight]> heightmap{std::make_unique<double [][Constants::WorldHeight]>(Constants::WorldWidth)};

如果您还没有,您还必须#include &lt;memory&gt;

没有什么需要改变的1make_unique 将为您之前拥有的完全相同的连续二维数组分配存储空间,只是动态分配而不是占用堆栈空间。而unique_ptr 足够聪明,可以在拥有它的类实例消失时自动释放存储空间。


1 只可能是真的。 std::unique_ptr&lt;Type[]&gt; 支持使用[] 进行下标,因此您当前的代码heightmap[x][y] 将继续工作。如果您在任何地方使用数组到指针衰减而不使用下标,您现在需要heightmap.get()&amp;heightmap[0][0] 而不仅仅是裸数组名称。

【讨论】:

  • 感谢本的所有帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-12
  • 2013-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多