我有一個使用參考的程式運行良好(沒有提示錯誤),但我決定使用分配在虛擬記憶體上的指標到指標陣列,因為我可以使用變數作為陣列的大小。
當我打破while (m_Window.isOpen())回圈時,即當我關閉游戲視窗并且游戲結束時,會提示錯誤。我注意到當我嘗試擦除Engine::cleanVirtualMemory()函式中的虛擬記憶體時程式會中斷。我注意到它在那里是因為我放了兩個標志(cout << "running1" << endl;和cout << "running2" << endl),我可以只顯示第一個標志。
然后它會提示一個帶有以下訊息的視窗:
HEAP CORRUPTION DETECTED after normal block.. CRT 檢測到應用程式在堆緩沖區結束后寫入記憶體
主檔案
#include "Engine.h"
using namespace sf;
int main(){
Engine Motor;
Motor.run();
Motor.cleanVirtualMemory();
}
引擎.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();
};
引擎.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;
}
結構生成器.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);
In the following code, you can see where I use pointers, I have erased code just to simplify.
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;
}
uj5u.com熱心網友回復:
我們來看看Engine類的宣告。
class Engine{
private:
// Lots of variables ....
Vector2i m_ArenaSize;
Vector2f * vectorStructureArray = new Vector2f[m_ArenaSize.y * m_ArenaSize.x * 4];
您班級的第一個成員Engine被稱為m_ArenaSize。這是在構造 a 時將構造的第一個類成員Engine。這就是 C 中物件構造的作業方式:構造新物件時,新物件的所有成員都按宣告順序構造。
你的類的第二個成員Engine是這個vectorStructureArray指標。它將被分配以指向一個具有動態大小的陣列,該陣列new使用構造m_ArenaSize的兩個自己的成員x和y.
現在,讓我們看一下Engine's 的建構式:
Engine::Engine() {
好的。那是你的建構式。因此,根據我們的計劃,將在's 的建構式的初始化部分(這里沒有)中,m_ArenaSize因為它沒有顯式構造,所以將得到默認構造。Engine如果你調查什么m_ArenaSize是默認建構式,你會發現它默認x為y0。
這就是構建vectorStructureArray指標的內容,作為Engine默認初始化的第二個業務順序。并且,因為它的x和y為 0,指標將指向總共 0 個值。
m_ArenaSize = Vector2i(10, 10);
直到現在,默認構造的才被m_ArenaSize替換為不同的主題,具有不同的x和y值。顯示的代碼清楚地期望指標被重新分配,以反映m_ArenaSize新的x和y值。但是 C 不能以這種方式作業。vectorStructureArray已經建成。它不會僅僅因為一個不同的類成員被替換而再次構造。后續代碼的假設是新的x和y值,這會導致相當明顯的記憶體損壞。
同樣的錯誤logicStructureArray也發生在 .
這些只是所示代碼中有關記憶體分配的前兩個主要錯誤。有幾種方法可以修復它們,但修復錯誤最簡單的方法是讓它們在邏輯上首先不可能發生。如果從不使用new和相關的錯誤,從邏輯上講是不可能發生的。delete現代 C 代碼很少使用newand delete,而是使用 C 庫的許多容器的服務。
在這里,兩個指標都可以簡單地替換為std::vector,其resize()成員負責分配兩個向量的大小。而且,作為額外的獎勵,所有分配的記憶體都會自動釋放,自動防止所有記憶體泄漏。
Replacing all the error-prone new and delete logic with std::vector will fix all memory-related issues in the shown code, the only thing you will have to make sure is that the vectors are correctly resize()d.
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/454247.html
標籤:c pointers sfml dynamic-memory-allocation dynamic-arrays
下一篇:c :通過參考傳遞陣列
