我正在创建一个版本的康威的生命游戏。它最终将在Arduino上运行,并将控制led,因此内存占用很重要。似乎我有一个内存泄漏,我相信这个泄漏发生在释放一个二维数组。如果有人能帮我做这件事,我将非常感激。
谢谢,乔
VLD的输出为:
c:projectsgameoflifecppgameoflifecppgameoflifecpp.cpp (72): GameOfLifeCPP.exe!GenerateGrid + 0xA bytes
c:projectsgameoflifecppgameoflifecppgameoflifecpp.cpp (185): GameOfLifeCPP.exe!ProcessGrid + 0x7 bytes
c:projectsgameoflifecppgameoflifecppgameoflifecpp.cpp (46): GameOfLifeCPP.exe!wmain + 0x9 bytes
f:ddvctoolscrt_bldself_x86crtsrccrtexe.c (552): GameOfLifeCPP.exe!__tmainCRTStartup + 0x19 bytes
f:ddvctoolscrt_bldself_x86crtsrccrtexe.c (371): GameOfLifeCPP.exe!wmainCRTStartup
0x7C817077 (File and line number not available): kernel32.dll!RegisterWaitForInputIdle + 0x49 bytes
代码是:
// GameOfLifeCPP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <vld.h>
#define WIDTH 75
#define HEIGHT 88
#define GENERATION_COUNT_LIMIT -1
long _generationCount = 0;
// These get set by controls on the table
long _delay = 1000;
bool _run = true;
bool _trail = true;
bool _randomize = false;
char* _colours = "roy";
int _tmain(int argc, _TCHAR* argv[])
{
system("pause");
short** grid = GenerateGrid(false);
short** trailGrid = GenerateGrid(true); // This is used to record all prev cells
while(_run)
{
if (_randomize)
{
grid = GenerateGrid(false);
trailGrid = GenerateGrid(true);
// Fade out LEDs
// Clear the historical grids that we compare
_randomize = false;
_generationCount = 0;
}
OutputGrid(grid, trailGrid);
if (_trail)
trailGrid = CalculateTrailGrid(grid, trailGrid);
short** nextGrid = ProcessGrid(grid);
// Release the old grid
for(int i = 0; i < sizeof(nextGrid); i++)
{
delete(grid[i]);
}
delete(grid);
grid = nextGrid;
// We don't want to just sleep we need to find out the start and end time
Sleep(_delay);
bool foundRecurance = false;
// Need to detect recurence, have a buffer of 5-10 prev grids and one
// hundredth ago, one thousanth etc that we compare to.
_generationCount++;
if (foundRecurance || _generationCount == GENERATION_COUNT_LIMIT)
_randomize = true;
_CrtDumpMemoryLeaks();
//system("pause");
}
return 0;
}
short** GenerateGrid(bool empty)
{
// The coordinates are y,x because it is simpler to output a row of chars
// when testing in the command line than it is to output a column of chars
short** grid = new short*[HEIGHT];
for(int y = 0; y < HEIGHT; y++)
{
short* row = new short[WIDTH];
for(int x = 0; x < WIDTH; x++)
{
// There is no point creating random numbers that we aren't going
// to use
if (empty)
row[x] = 0;
else
row[x] = rand() % 5 == 1 ? 1 : 0;
// Might want to adjust this or make it random
}
grid[y] = row;
}
return grid;
}
void OutputGrid(short** grid, short** trailGrid)
{
// This is terribly inefficent but I don't care since it is only for
// testing on my laptop
system("cls");
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
int curState = grid[y][x];
if (curState == 0 && _trail) // If it isn't alive then show the trail
curState = trailGrid[y][x];
switch (curState)
{
case 0: SetConsoleTextAttribute(hConsole, 0); break;
case 1: SetConsoleTextAttribute(hConsole, GetColour(0)); break;
case 2: SetConsoleTextAttribute(hConsole, GetColour(1)); break;
case -1: SetConsoleTextAttribute(hConsole, GetColour(2)); break;
}
//if (curState == 1 || curState == 2)
// std::cout << "*";
//else
std::cout << " ";
}
SetConsoleTextAttribute(hConsole, 15);
std::cout << std::endl;
}
}
int GetColour(int index)
{
int colour = 0;
switch(_colours[index])
{
case 'r': colour = 12; break;
case 'o': colour = 6; break;
case 'y': colour = 14; break;
}
colour = colour * 16;
return colour;
}
int ProcessCell(short** grid, int x, int y)
{
// Get the value for each of the surrounding cells
// We use the formula (x - 1 + WIDTH) % WIDTH because that means that if the
// Current cell is at 0,0 then top left is WIDTH-1,WIDTH-1 and so on.
// This makes the grid wrap around.
// We don't care if the cells value is 1 or 2 it is either live or dead
int topLeft = (
grid[(y - 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int top = (grid[(y - 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int topRight =
(grid[(y - 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int left = (grid[y][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int self = (grid[y][x] > 0) ? 1 : 0;
int right = (grid[y][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottomLeft =
(grid[(y + 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottom = (grid[(y + 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int bottomRight =
(grid[(y + 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
// Count up the surrounding cells to decide the current cell's state
int liveCount = topLeft + top + topRight + left +
right + bottomLeft + bottom + bottomRight;
int live = 0;
if (self > 0)
{
// Both are alive, just different colours
if (liveCount == 2)
live = 1;
if (liveCount == 3)
live = 2;
}
else if (liveCount == 3)
{
// Brought back to life, we don't care that it is the wrong
// colour - it looks better
live = 1;
}
return live;
}
short** ProcessGrid(short** grid)
{
short** nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
nextGrid[y][x] = ProcessCell(grid, x, y);
}
}
return nextGrid;
}
short** CalculateTrailGrid(short** grid, short** trailGrid)
{
// Any previously live cells are marked
short** nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
{
int state = grid[y][x];
if (state == 0)
state = trailGrid[y][x]; // Not alive currently but was
if (state != 0)
state = -1;
nextGrid[y][x] = state;
}
}
return nextGrid;
}
只需在记事本中快速清理5分钟…我应该给你一些建议……避免任何可能的内存泄漏…
#include "stdafx.h"
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <vld.h>
#include <vector>
#define WIDTH 75
#define HEIGHT 88
#define GENERATION_COUNT_LIMIT -1
long _generationCount = 0;
// These get set by controls on the table
long _delay = 1000;
bool _run = true;
bool _trail = true;
bool _randomize = false;
char* _colours = "roy";
typedef std::vector<std::vector<short>> grid_t; // Use std::vector
int _tmain(int argc, _TCHAR* argv[])
{
system("pause");
grid_t grid = GenerateGrid(false);
grid_t trailGrid = GenerateGrid(true); // This is used to record all prev cells
while(_run)
{
if (_randomize)
{
grid = GenerateGrid(false);
trailGrid = GenerateGrid(true);
// Fade out LEDs
// Clear the historical grids that we compare
_randomize = false;
_generationCount = 0;
}
OutputGrid(grid, trailGrid);
if (_trail)
trailGrid = CalculateTrailGrid(grid, trailGrid);
grid_t nextGrid = ProcessGrid(grid);
// Release the old grid
grid = nextGrid;
// We don't want to just sleep we need to find out the start and end time
Sleep(_delay);
bool foundRecurance = false;
// Need to detect recurence, have a buffer of 5-10 prev grids and one
// hundredth ago, one thousanth etc that we compare to.
_generationCount++;
if (foundRecurance || _generationCount == GENERATION_COUNT_LIMIT)
_randomize = true;
_CrtDumpMemoryLeaks();
//system("pause");
}
return 0;
}
grid_t GenerateGrid(bool empty)
{
// The coordinates are y,x because it is simpler to output a row of chars
// when testing in the command line than it is to output a column of chars
grid_t grid;
for(int y = 0; y < HEIGHT; y++)
{
std::vector<short> row;
for(int x = 0; x < WIDTH; x++)
row[x] = empty ? 0 : rand() % 5 == 1 ? 1 : 0;
grid.push_back(row);
}
return grid;
}
void OutputGrid(const grid_t& grid, const grid_t& trailGrid)
{
// This is terribly inefficent but I don't care since it is only for
// testing on my laptop
system("cls");
HANDLE hConsole;
hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
for(int y = 0; y < HEIGHT; y++)
{
for(int x = 0; x < WIDTH; x++)
{
int curState = grid[y][x];
if (curState == 0 && _trail) // If it isn't alive then show the trail
curState = trailGrid[y][x];
switch (curState)
{
case 0: SetConsoleTextAttribute(hConsole, 0); break;
case 1: SetConsoleTextAttribute(hConsole, GetColour(0)); break;
case 2: SetConsoleTextAttribute(hConsole, GetColour(1)); break;
case -1: SetConsoleTextAttribute(hConsole, GetColour(2)); break;
}
}
SetConsoleTextAttribute(hConsole, 15);
std::cout << std::endl;
}
}
int GetColour(int index)
{
switch(_colours[index])
{
case 'r': return 16 * 12;
case 'o': return 16 * 6;
case 'y': return 16 * 14;
default: return 0;
}
}
int ProcessCell(const grid_t& grid, int x, int y)
{
// Get the value for each of the surrounding cells
// We use the formula (x - 1 + WIDTH) % WIDTH because that means that if the
// Current cell is at 0,0 then top left is WIDTH-1,WIDTH-1 and so on.
// This makes the grid wrap around.
// We don't care if the cells value is 1 or 2 it is either live or dead
int topLeft = (grid[(y - 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int top = (grid[(y - 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int topRight = (grid[(y - 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int left = (grid[y][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int self = (grid[y][x] > 0) ? 1 : 0;
int right = (grid[y][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottomLeft = (grid[(y + 1 + HEIGHT) % HEIGHT][(x - 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
int bottom = (grid[(y + 1 + HEIGHT) % HEIGHT][x] > 0) ? 1 : 0;
int bottomRight = (grid[(y + 1 + HEIGHT) % HEIGHT][(x + 1 + WIDTH) % WIDTH] > 0) ? 1 : 0;
// Count up the surrounding cells to decide the current cell's state
int liveCount = topLeft + top + topRight + left + right + bottomLeft + bottom + bottomRight;
int live = 0;
if (self > 0)
{
// Both are alive, just different colours
if (liveCount == 2)
live = 1;
if (liveCount == 3)
live = 2;
}
else if (liveCount == 3)
{
// Brought back to life, we don't care that it is the wrong
// colour - it looks better
live = 1;
}
return live;
}
grid_t ProcessGrid(const grid_t& grid)
{
grid_t nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
nextGrid[y][x] = ProcessCell(grid, x, y);
}
return nextGrid;
}
grid_t CalculateTrailGrid(const grid_t& grid, const grid_t& trailGrid)
{
// Any previously live cells are marked
grid_t nextGrid = GenerateGrid(true);
for (int y = 0; y < HEIGHT; y++)
{
for (int x = 0; x < WIDTH; x++)
nextGrid[y][x] = state == 0 ? trailGrid[y][x] : -1;
}
return nextGrid;
}