无法加载ntdll.dll

Cannot load ntdll.dll

本文关键字:dll ntdll 加载      更新时间:2023-10-16

我已经研究这个问题一段时间了,我想我已经缩小了我的问题范围。

这是错误输出

Critical error detected c0000374
Duke's Army.exe has triggered a breakpoint.
Exception thrown at 0x77E49841 (ntdll.dll) in Duke's Army.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77E7C8D0).
Unhandled exception at 0x77E49841 (ntdll.dll) in Duke's Army.exe: 0xC0000374: A heap has been corrupted (parameters: 0x77E7C8D0).
The program '[14436] Duke's Army.exe' has exited with code 0 (0x0).

调用堆栈如下

ucrtbased.dll!0f8aa672()    Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for ucrtbased.dll] 
[External Code] 
>   Duke's Army.exe!Tile::Tile() Line 19    C++
[External Code] 
Duke's Army.exe!Map::Map(int w, int h) Line 70  C++
Duke's Army.exe!MapGenerator::init(int w, int h) Line 37    C++
Duke's Army.exe!MapGenerator::MapGenerator(int w, int h) Line 13    C++
Duke's Army.exe!PlayGameState::PlayGameState(Game * g) Line 13  C++
Duke's Army.exe!main() Line 11  C++
[External Code] 

其他答案建议删除未正确声明的静态成员或类似的内容。然而,在(假定的(受影响的类中,有一个静态向量我找不到删除的方法。有什么建议吗?

[这是我认为错误发生的类](调用堆栈中的第19行是默认构造函数定义的开始(

Tile.h

class Tile
{
public:
    static std::vector<Tile> tiles;
    // Constructors and methods...
    // Method used in constructors to add to static tiles       
    void Tile::init(const std::string& n, const sf::Color& c) {
        this->name = n;
        this->color = c;
        tiles.push_back(*this);
    }
    Tile(std::string n, sf::Color c) {
        init(n, c);
    };
    Tile() {
        init("bounds", sf::Color::Black);
    }
    const static Tile wall;
    const static Tile floor;
    const static Tile bounds;
    const static float TILE_SIZE;
};

静态成员在Tile.cpp 中声明

std::vector<Tile> Tile::tiles = std::vector<Tile>(3);
const Tile Tile::wall("wall", sf::Color::White);
const Tile Tile::floor("floor", sf::Color::Green);
const Tile Tile::bounds;
const float Tile::TILE_SIZE = 16.f;

您的代码默认初始化Tile::tiles如下:

std::vector<Tiles> Tile::tiles = std::vector<Tile>(3);

vector的构造不仅设置容量,它还创建了一个包含3个元素的向量,默认构造,这将导致对init的3次调用,在init中,您可以

tiles.push_back(*this);

push_back尝试将向量增加一,然后复制构造新添加的元素。这里的关键部分是增长向量

再次:记住,这是在构建向量的过程中发生的。

您将创建一个超出矢量目标大小的新元素,或者重写当前正在填充的元素。

std::vector的GNU实现在构造函数完成之前不会设置向量大小。结果,您会被覆盖:

#include <iostream>
#include <string>
#include <vector>
struct S {
    std::string s_;
    static std::vector<S> tiles;
    S() { std::cout << "S()n"; init("default"); }
    S(const std::string& s) {
        std::cout << "S(" << (void*) this << " with " << s << ")n";
        init(s);
    }
    S(const S& rhs) {
        std::cout << (void*) this << " copying " << (void*)&rhs << " (" << rhs.s_ << ")n";
        s_ = rhs.s_;
        s_ += " copy";
    }
    void init(const std::string& s) {
        s_ = s;
        std::cout << "init " << (void*)this << " " << s_ << "n";
        tiles.push_back(*this);  // makes copy
    }
};

std::vector<S> S::tiles = std::vector<S>(3);
int main() {
    for (const auto& el : S::tiles) {
        std::cout << el.s_ << "n";
    }
}

输出http://ideone.com/0dr7L2

S()
init 0x9e67a10 default
0x9e67a10 copying 0x9e67a10 ()
S()
init 0x9e67a14 default
0x9e67a14 copying 0x9e67a14 ()
S()
init 0x9e67a18 default
0x9e67a18 copying 0x9e67a18 ()
 copy
 copy
 copy

所以您在启动应用程序时引入了UB。

在上面的示例中,复制构造函数默认在执行复制之前初始化其目标,并且由于它正在复制自己,这导致rhs.s_被清除。这就是为什么我们得到"copy"而不是"default copy"。

---编辑---

(无效,如@underscore_d所指出(

---编辑2-

MSVC矢量实现做到了这一点:

explicit vector(size_type _Count)
    : _Mybase()
    {   // construct from _Count * value_type()
    if (_Buy(_Count))
        {   // nonzero, fill it
        _TRY_BEGIN
        _Uninitialized_default_fill_n(this->_Myfirst(), _Count,
            this->_Getal());
        this->_Mylast() += _Count;
        _CATCH_ALL
        _Tidy();
        _RERAISE;
        _CATCH_END
        }
    }

关键部分是:

        _Uninitialized_default_fill_n(this->_Myfirst(), _Count,
            this->_Getal());
        this->_Mylast() += _Count;

在填充过程中,您的push_back将使_MyLast增加3个位置,然后ctor的下一行将使_MyLast再增加3个。

以下是上面在Visual Studio下运行的相同代码:http://rextester.com/WNQ21225