2015-01-15 5 views
0

콘솔에서 이중 버퍼링을 사용하려고합니다. 나는이 코드를 작성했으나 컴파일했다. 그러나 생성 된 콘솔에서는 맨 아래 줄이 거의 무작위로 채워져있다. CHAR_INFO cur[Width*Height];CHAR_INFO cur[Width*Height+200];으로 변경하는 것은 도움이되지만 왜 너비 * 높이의 메모리가 부족한 지 이해할 수 없습니다.콘솔에서 이중 버퍼링을 할 때 왜 무작위 기호가 나타 납니까?

#include <windows.h> 
#include <ctime> 

#define xMax 80 
#define yMax 25 
#define fPS 250 
#define Delay 60 

class dbconsole 
{ 
private: 
    int width, height, FPS, delay; 
    HANDLE h0, h1; 
    CHAR_INFO *chiBuffer; 
    bool curBuffer; 
    int drawingTimer; 
public: 
    dbconsole(int Width, int Height, int fps) 
    { 
     CHAR_INFO cur[Width*Height]; 
     width = Width; 
     height = Height; 
     FPS = fps; 
     preparebuffer(h0); 
     preparebuffer(h1); 
     chiBuffer = cur; 
     curBuffer = 0; 
     drawingTimer = clock(); 
    } 
    void preparebuffer(HANDLE &h) 
    { 
     CONSOLE_CURSOR_INFO cursor; 
     cursor.bVisible = false; 
     cursor.dwSize = 1; 
     h = CreateConsoleScreenBuffer(
       GENERIC_READ | GENERIC_WRITE, 
       FILE_SHARE_READ | FILE_SHARE_WRITE, 
       NULL, 
       CONSOLE_TEXTMODE_BUFFER, 
       NULL); 
     SetConsoleCursorInfo(h, &cursor); 
    } 
    void putpixel(int x, int y, CHAR_INFO input) 
    { 
     chiBuffer[x+width*y]=input; 
    } 
    void depict() 
    { 
     SMALL_RECT srctWriteRect; 
     srctWriteRect.Top = 0; 
     srctWriteRect.Left = 0; 
     srctWriteRect.Bottom = yMax-1; 
     srctWriteRect.Right = xMax-1; 
     if ((clock()-drawingTimer)*FPS>CLOCKS_PER_SEC) 
     { 
      if (curBuffer) 
      { 
       WriteConsoleOutput(h0, chiBuffer, {xMax,yMax}, {0,0}, &srctWriteRect); 
       SetConsoleActiveScreenBuffer(h0); 
      } 
      else 
      { 
       WriteConsoleOutput(h1, chiBuffer, {xMax,yMax}, {0,0}, &srctWriteRect); 
       SetConsoleActiveScreenBuffer(h1); 
      } 
      curBuffer=!curBuffer; 
      drawingTimer = clock(); 
     } 
    } 
}; 

int main(void) 
{ 
    dbconsole myConsole = dbconsole(xMax,yMax,fPS); 
    SetConsoleTitle("Use arrow keys to control character"); 
    long long movetimer = clock(); 
    int x = 0, y = 0; 
    while (true) 
    { 
     for (int i = 0; i < xMax; i++) for (int j = 0; j < yMax; j++) myConsole.putpixel(i,j, {' ',16}); 
     if ((clock()-movetimer)*Delay>CLOCKS_PER_SEC) 
     { 
      if (GetAsyncKeyState(VK_RIGHT)) 
      { 
       movetimer = clock(); 
       if (x < xMax-1) x++; 
      } 
      if (GetAsyncKeyState(VK_LEFT)) 
      { 
       movetimer = clock(); 
       if (x > 0) x--; 
      } 
      if (GetAsyncKeyState(VK_DOWN)) 
      { 
       movetimer = clock(); 
       if (y < yMax-1) y++; 
      } 
      if (GetAsyncKeyState(VK_UP)) 
      { 
       movetimer = clock(); 
       if (y > 0) y--; 
      } 
      if (GetAsyncKeyState(VK_ESCAPE)) return 0; 
     } 
     myConsole.putpixel(x,y,{1,15|16}); 
     myConsole.depict(); 
    } 
} 

나는 문제가 chiBuffer에 해당하는 일부 메모리가 예약되지 않는다는 사실 때문이라고 생각,하지만 난 왜하지 않습니다. 문제는 무엇입니까? 여기

+3

왜'std :: vector'를 사용하지 않을까요? –

답변

3

:

dbconsole(int Width, int Height, int fps) 
{ 
    CHAR_INFO cur[Width*Height]; 
    .... 
    chiBuffer = cur; 

cur는 지역 변수 없으며, 생성자가 왼쪽되면, 그것은 더 이상 존재하지. 이 시점에서 chiBuffer은 유효한 포인터가 아니며이를 사용하면 정의되지 않은 동작이 발생합니다.

// also: #include <vector> at the top 
std::vector<CHAR_INFO> chiBuffer; 

등처럼 생성자에서 초기화 :

간단한 해결책은 chiBufferstd::vector을하는 것입니다

dbconsole(int Width, int Height, int fps) 
    : chiBuffer(Width * Height) 
{ 
    // cur no longer necessary. 

만 추가 변경이 필요

//      v----------v--- here 
WriteConsoleOutput(h0, &chiBuffer[0], {xMax,yMax}, {0,0}, &srctWriteRect); 

벡터에서 포인터를 추출하려면 C 기능 WriteConsoleOutput을 이해할 수 있습니다. std::vector은 요소를 메모리와 같이 배열에 연속적으로 저장하기 때문에 효과적입니다.

관련 문제