Странное поведение массива в классах вместе с Windows DC (C ++)?

Я работаю над созданием текстовой игры для Windows, и у меня возникла проблема (я полагаю), что массивы не работают так же, как в рамках класса, так и в основной функции. Насколько я могу судить, это какое-то взаимодействие между большим членом класса массива (или большим общим количеством переменных) и Windows, создающей DC или другие вызовы и / или переменные Windows API.

Я хочу иметь класс Map с двумерным массивом плиток. Плитка — это просто простая структура с базовой информацией о плитке. Я хотел бы сделать массив 256 х 256. Насколько я понимаю, это не должно быть проблемой. Каждая плитка должна быть 32 байта. Это всего 2 МБ для массива.

Однако игра вылетает, когда я объявляю переменную класса Map в функции main, а затем выполняю действия с контроллерами домена Windows. Возвращаемое значение, кажется, изменяется, в текущей форме оно обычно возвращает 255, но я также получил «процесс завершен со статусом -1073741571». Массив 128 x 128 работает в классе, хотя. Это также работает нормально, если я удаляю массив или код в DisplayScreen. И, как я и предполагал, это также работает, если я просто перемещаю массив Tiles в основную функцию.

Я честно сбит с толку. Я понятия не имею, в чем будет разница. Ничто не выходит за рамки. Не имеет значения, является ли это публичным или частным членом. Все нединамические члены класса должны быть объявлены в стеке, и это не должно работать по-другому в классе, в противном случае, верно?

Для другой информации я использую Code :: Blocks с компилятором Min GW. Все актуально. Я использую Windows 10. У меня тоже не должно быть проблем со спецификацией компьютера, но если это имеет значение, у меня 16 ГБ памяти и 4 ГГц процессор Athlon FX 8.

Изменить: вот полный код, так что ничего не пропущено

Game.h:

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

struct Tile
{
char chr[2];
int  r[2], b[2], g[2];

bool solid;
bool translucent;
int  opacity;
};

class Map
{
Tile tileMap[256][256];

public:
Map();

};

Map::Map()
{
int i, j;

for(i=0;i<256;i++)
{
for(j=0;j<256;j++)
{
tileMap[i][j].chr[0] = 'X';
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;

tileMap[i][j].chr[1] = ' ';
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;

tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}

main.cpp:

#include <windows.h>
#include "Game.h"
#define FRAMERATE 60

//Function declarations
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
void DisplayScreen(HWND pWnd, Map &pMap);

//Make the class name into a global variable
char strClassName[ ] = "GameApp";

int WINAPI WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpstrArgument,
int nCmdShow)
{
HWND hWnd;               //This is the handle for our window
MSG messages;            //Here messages to the application are saved
WNDCLASSEX wndClassEx;   //Data structure for the windowclass

Map test;

DWORD  sysTimer;
DWORD  sysPrevTime = 0;
DWORD  timerDelta = 1000 / FRAMERATE;

//Get a handle for the whole screen
HDC hDC = GetDC(NULL);

//Initalize the Window structure
wndClassEx.hInstance = hThisInstance;
wndClassEx.lpszClassName = strClassName;
wndClassEx.lpfnWndProc = WindowProcedure;
wndClassEx.style = CS_DBLCLKS;
wndClassEx.cbSize = sizeof (WNDCLASSEX);
wndClassEx.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wndClassEx.hCursor = LoadCursor (NULL, IDC_ARROW);
wndClassEx.lpszMenuName = NULL;                 //No menu
wndClassEx.cbClsExtra = 0;
wndClassEx.cbWndExtra = 0;
wndClassEx.hbrBackground = CreateSolidBrush(RGB(0,0,0));

//Register the window class, and if it fails quit the program
if (!RegisterClassEx (&wndClassEx))
return 0;

//Create Window with registered window class
hWnd = CreateWindowEx (
0,
strClassName,                //Class name
"Game Test",                 //Title Text
WS_OVERLAPPEDWINDOW,         //default window type
0,                           //X pos of window at top left
0,                           //Y pos of window at top left
GetDeviceCaps(hDC, HORZRES), //Set window width to screen width
GetDeviceCaps(hDC, VERTRES), //Set window height to screen height
HWND_DESKTOP,                //Child-window to desktop
NULL,                        //No menu
hThisInstance,               //Program Instance handler
NULL);                       //No Window Creation data//Removes borders from the window
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP);
//Make the window visible on the screen
ShowWindow (hWnd, nCmdShow);

//Run the message and game loop
while (true)
{
while(PeekMessage(&messages,NULL,0,0, PM_REMOVE))
{
if (messages.message == WM_QUIT)
{
ReleaseDC(NULL, hDC);
DestroyWindow(hWnd);
return 0;
}

TranslateMessage(&messages);
DispatchMessage(&messages);
}

sysTimer = timeGetTime();

if (sysTimer >= (sysPrevTime + timerDelta) )
{
sysPrevTime = sysTimer;
DisplayScreen(hWnd, test);
}

}
}

//This function is called by the Windows function DispatchMessage()
LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage (0); //Send WM_QUIT to the message queue
break;

default:
return DefWindowProc (hWnd, message, wParam, lParam);
}

return 0;
}

void DisplayScreen(HWND pWnd, Map &pMap)
{
HDC hDC = GetWindowDC(pWnd);
HDC hdcBuf = CreateCompatibleDC(hDC);

HBITMAP hbmBuf = CreateCompatibleBitmap(hDC, 800, 600);
HFONT hMapFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");
HFONT hTxtFont = CreateFont(17,11,0,0,400,FALSE,FALSE,FALSE,ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,ANTIALIASED_QUALITY,DEFAULT_PITCH | FF_MODERN,"Lucida Console");

SelectObject(hdcBuf, hbmBuf);
SelectObject(hdcBuf, hMapFont);

SetBkColor(hdcBuf, RGB(0,0,0));
SetTextColor(hdcBuf, RGB(255,255,255));

//Draw to the buffer
TextOut(hdcBuf, 10, 10, "Hello World   @", 15);

//Tranfers the buffer to the Screen
BitBlt(hDC, 100, 100, 800, 600, hdcBuf, 0, 0, SRCCOPY);

//Release all object handles
DeleteObject(hTxtFont);
DeleteObject(hMapFont);
DeleteObject(hbmBuf);

DeleteDC(hdcBuf);
ReleaseDC(pWnd, hDC);
}

Он падает даже с одним экземпляром чего-то, что создает DC. Он отлично работает, в противном случае создает и уничтожает контроллеры домена и отображает растровое изображение снова и снова, даже если я оставлю его на час. Когда я создаю этот класс с большим массивом, он просто умирает.

Я действительно использовал функцию Display в качестве функции класса, и я переместил ее, потому что думал, что это проблема, но это не так.

Интересно, если я поменяю объявление с «Тест карты»; «Карта * тест = новая карта;» и измените остальную часть программы соответствующим образом, она работает. Честно говоря, делать это просто глупо, и я думаю, что это замедлит все, если у меня не будет веской причины положить все в кучу. Плюс я не люблю бинты. Если есть проблема, я бы лучше ее решил.

Есть идеи?

-2

Решение

У вас переполнение стека (условие, а не веб-сайт).

0

Другие решения

Проблема может быть воспроизведена в этой программе:

int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
Map test;
return 0;
}

Это терпит неудачу, потому что это достигает предела стека.

Также tileMap[i][j].chr[2] вне границ. Объявлен как char chr[2]; действительный индекс 0 и 1. Он может идти только до tileMap[i][j].chr[1]

то же самое b[], r[], а также g[]

Изменить Map класс, чтобы он выделял память на кучу и исправлял chr:

class Map
{
//Tile tileMap[256][256];
Tile **tileMap;
public:
Map();
~Map();
};

Map::Map()
{
int i, j;

tileMap = new Tile*[256];
for (i = 0; i < 256; i++)
tileMap[i] = new Tile[256];

for (i = 0; i<256; i++)
{
for (j = 0; j<256; j++)
{
//tileMap[i][j].chr[1] = 'X';
tileMap[i][j].chr[0] = 'X';  //<== meant to be 0?
tileMap[i][j].b[0] = 255;
tileMap[i][j].r[0] = 255;
tileMap[i][j].g[0] = 255;

//tileMap[i][j].chr[2] = ' ';
tileMap[i][j].chr[1] = ' '; //<== meant to be 1?
tileMap[i][j].b[1] = 0;
tileMap[i][j].r[1] = 0;
tileMap[i][j].g[1] = 0;

tileMap[i][j].solid = false;
tileMap[i][j].translucent = false;
tileMap[i][j].opacity = 255;
}
}
}

Map::~Map()
{
int i = 0;
for (i = 0; i < 256; i++)
delete[]tileMap[i];
delete[]tileMap;
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector