我怎样才能解决这个问题? “正常块后检测到堆损坏。CRT 检测到应用程序在堆缓冲区结束后写入内存”
How can I fix this? " HEAP CORRUPTION DETECTED after normal block.. CRT detected that the application wrote to memory after end of heap buffer "
我有一个程序使用引用运行良好(没有提示错误),但我决定使用分配在虚拟内存上的指针到指针数组,因为我可以使用变量作为数组的大小。
当我打破 while (m_Window.isOpen())
循环时出现错误提示,换句话说当我关闭游戏 window 并且游戏结束时。我注意到当我尝试在 Engine::cleanVirtualMemory()
函数中擦除虚拟内存时程序中断了。我注意到它在那里,因为我放了两个标志(cout << "running1" << endl;
和 cout << "running2" << endl
),我只能显示第一个标志。
然后它会提示 window 并显示以下消息:
HEAP CORRUPTION DETECTED after normal block.. CRT detected that the application wrote to memory after end of heap buffer
main.cpp
#include "Engine.h"
using namespace sf;
int main(){
Engine Motor;
Motor.run();
Motor.cleanVirtualMemory();
}
Engine.h
#pragma once
#include <SFML/Graphics.hpp>
#include "StructureBuilder.h"
using namespace sf;
using namespace std;
class Engine{
private:
// Lots of variables ....
Vector2i m_ArenaSize;
Vector2f * vectorStructureArray = new Vector2f[m_ArenaSize.y * m_ArenaSize.x * 4];
int** logicStructureArray = new int*[m_ArenaSize.y];
// Lots of variables ....
//Gameloop
void Input();
void Update(dtAsSeconds);
void Draw();
public:
Engine();
void run();
void cleanVirtualMemory();
};
Engine.cpp
#include "Engine.h"
#include <iostream>
using namespace sf;
Engine::Engine() {
/// lots of variables and data ...
/// Making arena
m_ArenaSize = Vector2i(10, 10);
StructureBuilder(arenaStructures, vectorStructureArray, logicStructureArray, m_ArenaSize);
}
void Engine::run() {
//Timing
Clock clock;
while (m_Window.isOpen()) {
// Each time clock restarted, dt = time elapse (from 0 to now, then clock = 0)
Time dt = clock.restart();
// Convert time elapse to seconds
double dtAsSeconds = dt.asSeconds();
// Call each part of the game in turn
Input();
Update(dtAsSeconds);
Draw();
}
}
void Engine::cleanVirtualMemory() {
// Deallocate Virtual Memory
// first flag
cout << "running1" << endl;
for (int i = m_ArenaSize.x - 1; i > -1; i--) {
delete[] logicStructureArray[i];
}
delete[] logicStructureArray;
logicStructureArray = NULL;
delete[] vectorStructureArray;
vectorStructureArray = NULL;
// second flag
cout << "running2" << endl;
}
StructureBuilder.h
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string.h>
using namespace sf;
using namespace std;
Vector2i StructureBuilder(VertexArray& rVA, Vector2f* rA, int** rLA, Vector2i ArenaSize);
在下面的代码中,您可以看到我在哪里使用了指针,为了简化,我删除了代码。
StructureBuilder.cpp
#include "StructureBuilder.h"
Vector2i StructureBuilder(VertexArray& rVA, Vector2f* rA, int** rLA, Vector2i ArenaSize) {
//Set map properties and VertexArrayType
double tileSize = 100;
double Height = ArenaSize.y * tileSize;
double angle = 30;
int offset = 0;
int Primitive = 4;
int currentVertex = 0;
rVA.setPrimitiveType(Quads);
rVA.resize(ArenaSize.x * ArenaSize.y * 4);
// First build graphically our map structures's using char strings
string stringArray[10];
stringArray[0] = "1000000000";
stringArray[1] = "0000000000";
stringArray[2] = "0000010000";
stringArray[3] = "0000000000";
stringArray[4] = "0000000000";
stringArray[5] = "0000000000";
stringArray[6] = "0000000000";
stringArray[7] = "0000000000";
stringArray[8] = "0000000000";
stringArray[9] = "0000000000";
// Convert stringArray to charArray, finally charArray to intArray
char** charArray = new char*[ArenaSize.y];
Vector2f Vector1;
Vector2f Vector2;
Vector2f Vector3;
Vector2f Vector4;
for (int i = 0; i < ArenaSize.x; i++) {
charArray[i] = new char[ArenaSize.x];
rLA[i] = new int[ArenaSize.x];
}
for (int i = 0; i < ArenaSize.x; i++) {
for (int j = 0; j < ArenaSize.y; j++) {
charArray[j][i] = stringArray[j][i];
rLA[j][i] = charArray[j][i] - 48;
// Check when we have a value greater or equal to 1, if yes build a structure.
if (rLA[j][i] == 1) {
Vector1 = Vector2f(Value..., Value...);// in order to understand I dont put the whole calculation here
Vector2 = Vector2f(Value..., Value ...); // is just trigonometry to find vertex
Vector3 = Vector2f(Value..., Value ...);
Vector4 = Vector2f(Value..., Value ...);
rVA[currentVertex + 0].position = Vector1;
rVA[currentVertex + 1].position = Vector2;
rVA[currentVertex + 2].position = Vector3;
rVA[currentVertex + 3].position = Vector4;
rVA[currentVertex + 0].texCoords = Vector2f(42, 0); // coords on my spritesheet
rVA[currentVertex + 1].texCoords = Vector2f(86, 24);
rVA[currentVertex + 2].texCoords = Vector2f(42, 49);
rVA[currentVertex + 3].texCoords = Vector2f(0, 24);
rA[currentVertex + 0] = Vector1; //Later I use this to tell the program where to construct restrictions (where the player can't move)
rA[currentVertex + 1] = Vector2;
rA[currentVertex + 2] = Vector3;
rA[currentVertex + 3] = Vector4;
}
currentVertex = currentVertex + Primitive;
}
}
// Deallocate Virtual Memory
for (int i = ArenaSize.x - 1; i > -1; i--) {
delete[] charArray[i];
}
delete[] charArray;
charArray = NULL;
return ArenaSize;
}
我们来看看Engine
class.
的声明
class Engine{
private:
// Lots of variables ....
Vector2i m_ArenaSize;
Vector2f * vectorStructureArray = new Vector2f[m_ArenaSize.y * m_ArenaSize.x * 4];
您 Engine
class 的第一个成员叫 m_ArenaSize
。这是在构造 Engine
时构造的第一个 class 成员。这就是 C++ 中对象构造的工作方式:构造新对象时,新对象的所有成员都按声明顺序构造。
您的 Engine
class 的第二个成员是这个 vectorStructureArray
指针。它将被分配指向一个数组,具有动态大小,使用 m_ArenaSize
自己构造的两个成员 x
和 y
得到 new
ed。 =53=]
现在,让我们看一下 Engine
的构造函数:
Engine::Engine() {
好的。那是你的构造函数。所以,根据我们的计划,m_ArenaSize
将得到 default-constructed,因为它没有显式构造,在 Engine
的构造函数的初始化部分(这里有 none) .如果您调查 m_ArenaSize
的默认构造函数,您会发现它默认 x
和 y
为 0.
这就是构造 vectorStructureArray
指针的原因,作为 Engine
默认初始化的第二个业务顺序。并且,因为它的 x
和 y
是 0,所以指针将指向总共 0 个值。
m_ArenaSize = Vector2i(10, 10);
现在 default-constructed m_ArenaSize
被替换为不同的主题,具有不同的 x
和 y
值。显示的代码显然希望指针重新分配,以反映 m_ArenaSize
的新 x
和 y
值。但是 C++ 不是这样工作的。 vectorStructureArray
已经建成。它不会仅仅因为替换了一个不同的 class 成员而再次构造。后续代码的假设是新的 x
和 y
值,这会导致相当明显的内存损坏。
logicStructureArray
也出现了同样的错误。
这些只是所示代码中有关内存分配的前两个主要错误。修复错误的方法有多种,但修复错误最简单的方法是从一开始就让错误在逻辑上不可能发生。如果从未使用过 new
和 delete
相关的错误,在逻辑上是不可能发生的。现代 C++ 代码很少使用 new
和 delete
,而是使用 C++ 库的许多容器的服务。
这里,两个指针都可以简单地替换为 std::vector
,其 resize()
成员负责分配两个向量的大小。而且,作为额外的奖励,所有分配的内存都会自动释放,自动防止所有内存泄漏。
将所有 error-prone new
和 delete
逻辑替换为 std::vector
将解决显示代码中的所有 memory-related 问题,您唯一要做的就是必须确保向量正确 resize
()d.
我有一个程序使用引用运行良好(没有提示错误),但我决定使用分配在虚拟内存上的指针到指针数组,因为我可以使用变量作为数组的大小。
当我打破 while (m_Window.isOpen())
循环时出现错误提示,换句话说当我关闭游戏 window 并且游戏结束时。我注意到当我尝试在 Engine::cleanVirtualMemory()
函数中擦除虚拟内存时程序中断了。我注意到它在那里,因为我放了两个标志(cout << "running1" << endl;
和 cout << "running2" << endl
),我只能显示第一个标志。
然后它会提示 window 并显示以下消息:
HEAP CORRUPTION DETECTED after normal block.. CRT detected that the application wrote to memory after end of heap buffer
main.cpp
#include "Engine.h"
using namespace sf;
int main(){
Engine Motor;
Motor.run();
Motor.cleanVirtualMemory();
}
Engine.h
#pragma once
#include <SFML/Graphics.hpp>
#include "StructureBuilder.h"
using namespace sf;
using namespace std;
class Engine{
private:
// Lots of variables ....
Vector2i m_ArenaSize;
Vector2f * vectorStructureArray = new Vector2f[m_ArenaSize.y * m_ArenaSize.x * 4];
int** logicStructureArray = new int*[m_ArenaSize.y];
// Lots of variables ....
//Gameloop
void Input();
void Update(dtAsSeconds);
void Draw();
public:
Engine();
void run();
void cleanVirtualMemory();
};
Engine.cpp
#include "Engine.h"
#include <iostream>
using namespace sf;
Engine::Engine() {
/// lots of variables and data ...
/// Making arena
m_ArenaSize = Vector2i(10, 10);
StructureBuilder(arenaStructures, vectorStructureArray, logicStructureArray, m_ArenaSize);
}
void Engine::run() {
//Timing
Clock clock;
while (m_Window.isOpen()) {
// Each time clock restarted, dt = time elapse (from 0 to now, then clock = 0)
Time dt = clock.restart();
// Convert time elapse to seconds
double dtAsSeconds = dt.asSeconds();
// Call each part of the game in turn
Input();
Update(dtAsSeconds);
Draw();
}
}
void Engine::cleanVirtualMemory() {
// Deallocate Virtual Memory
// first flag
cout << "running1" << endl;
for (int i = m_ArenaSize.x - 1; i > -1; i--) {
delete[] logicStructureArray[i];
}
delete[] logicStructureArray;
logicStructureArray = NULL;
delete[] vectorStructureArray;
vectorStructureArray = NULL;
// second flag
cout << "running2" << endl;
}
StructureBuilder.h
#pragma once
#include <SFML/Graphics.hpp>
#include <iostream>
#include <string.h>
using namespace sf;
using namespace std;
Vector2i StructureBuilder(VertexArray& rVA, Vector2f* rA, int** rLA, Vector2i ArenaSize);
在下面的代码中,您可以看到我在哪里使用了指针,为了简化,我删除了代码。
StructureBuilder.cpp
#include "StructureBuilder.h"
Vector2i StructureBuilder(VertexArray& rVA, Vector2f* rA, int** rLA, Vector2i ArenaSize) {
//Set map properties and VertexArrayType
double tileSize = 100;
double Height = ArenaSize.y * tileSize;
double angle = 30;
int offset = 0;
int Primitive = 4;
int currentVertex = 0;
rVA.setPrimitiveType(Quads);
rVA.resize(ArenaSize.x * ArenaSize.y * 4);
// First build graphically our map structures's using char strings
string stringArray[10];
stringArray[0] = "1000000000";
stringArray[1] = "0000000000";
stringArray[2] = "0000010000";
stringArray[3] = "0000000000";
stringArray[4] = "0000000000";
stringArray[5] = "0000000000";
stringArray[6] = "0000000000";
stringArray[7] = "0000000000";
stringArray[8] = "0000000000";
stringArray[9] = "0000000000";
// Convert stringArray to charArray, finally charArray to intArray
char** charArray = new char*[ArenaSize.y];
Vector2f Vector1;
Vector2f Vector2;
Vector2f Vector3;
Vector2f Vector4;
for (int i = 0; i < ArenaSize.x; i++) {
charArray[i] = new char[ArenaSize.x];
rLA[i] = new int[ArenaSize.x];
}
for (int i = 0; i < ArenaSize.x; i++) {
for (int j = 0; j < ArenaSize.y; j++) {
charArray[j][i] = stringArray[j][i];
rLA[j][i] = charArray[j][i] - 48;
// Check when we have a value greater or equal to 1, if yes build a structure.
if (rLA[j][i] == 1) {
Vector1 = Vector2f(Value..., Value...);// in order to understand I dont put the whole calculation here
Vector2 = Vector2f(Value..., Value ...); // is just trigonometry to find vertex
Vector3 = Vector2f(Value..., Value ...);
Vector4 = Vector2f(Value..., Value ...);
rVA[currentVertex + 0].position = Vector1;
rVA[currentVertex + 1].position = Vector2;
rVA[currentVertex + 2].position = Vector3;
rVA[currentVertex + 3].position = Vector4;
rVA[currentVertex + 0].texCoords = Vector2f(42, 0); // coords on my spritesheet
rVA[currentVertex + 1].texCoords = Vector2f(86, 24);
rVA[currentVertex + 2].texCoords = Vector2f(42, 49);
rVA[currentVertex + 3].texCoords = Vector2f(0, 24);
rA[currentVertex + 0] = Vector1; //Later I use this to tell the program where to construct restrictions (where the player can't move)
rA[currentVertex + 1] = Vector2;
rA[currentVertex + 2] = Vector3;
rA[currentVertex + 3] = Vector4;
}
currentVertex = currentVertex + Primitive;
}
}
// Deallocate Virtual Memory
for (int i = ArenaSize.x - 1; i > -1; i--) {
delete[] charArray[i];
}
delete[] charArray;
charArray = NULL;
return ArenaSize;
}
我们来看看Engine
class.
class Engine{
private:
// Lots of variables ....
Vector2i m_ArenaSize;
Vector2f * vectorStructureArray = new Vector2f[m_ArenaSize.y * m_ArenaSize.x * 4];
您 Engine
class 的第一个成员叫 m_ArenaSize
。这是在构造 Engine
时构造的第一个 class 成员。这就是 C++ 中对象构造的工作方式:构造新对象时,新对象的所有成员都按声明顺序构造。
您的 Engine
class 的第二个成员是这个 vectorStructureArray
指针。它将被分配指向一个数组,具有动态大小,使用 m_ArenaSize
自己构造的两个成员 x
和 y
得到 new
ed。 =53=]
现在,让我们看一下 Engine
的构造函数:
Engine::Engine() {
好的。那是你的构造函数。所以,根据我们的计划,m_ArenaSize
将得到 default-constructed,因为它没有显式构造,在 Engine
的构造函数的初始化部分(这里有 none) .如果您调查 m_ArenaSize
的默认构造函数,您会发现它默认 x
和 y
为 0.
这就是构造 vectorStructureArray
指针的原因,作为 Engine
默认初始化的第二个业务顺序。并且,因为它的 x
和 y
是 0,所以指针将指向总共 0 个值。
m_ArenaSize = Vector2i(10, 10);
现在 default-constructed m_ArenaSize
被替换为不同的主题,具有不同的 x
和 y
值。显示的代码显然希望指针重新分配,以反映 m_ArenaSize
的新 x
和 y
值。但是 C++ 不是这样工作的。 vectorStructureArray
已经建成。它不会仅仅因为替换了一个不同的 class 成员而再次构造。后续代码的假设是新的 x
和 y
值,这会导致相当明显的内存损坏。
logicStructureArray
也出现了同样的错误。
这些只是所示代码中有关内存分配的前两个主要错误。修复错误的方法有多种,但修复错误最简单的方法是从一开始就让错误在逻辑上不可能发生。如果从未使用过 new
和 delete
相关的错误,在逻辑上是不可能发生的。现代 C++ 代码很少使用 new
和 delete
,而是使用 C++ 库的许多容器的服务。
这里,两个指针都可以简单地替换为 std::vector
,其 resize()
成员负责分配两个向量的大小。而且,作为额外的奖励,所有分配的内存都会自动释放,自动防止所有内存泄漏。
将所有 error-prone new
和 delete
逻辑替换为 std::vector
将解决显示代码中的所有 memory-related 问题,您唯一要做的就是必须确保向量正确 resize
()d.