Jumer
Jumer

Reputation: 51

Segmentation fault GetConsoleScreenBufferInfo (WinApi) C++

I'm working with WinApi in C++ to change console properties and get the segmentation fault error when calling GetConsoleScreenBufferInfo() in the last two functions.

It's strange that if I reproduce the same piece of code -just calling GetConsoleScreenBufferInfo() with same declarations of HANDLE and PCONSOLE_SCREEN_BUFFER_INFO- in main() I get no error, but if I do so inside getPosCursorX() I still get the error.

namespace consola{

HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE);
PCONSOLE_SCREEN_BUFFER_INFO infoCon;

struct TamanoConsola
{
    COORD buffer;
    SMALL_RECT ventana;
} inicial;

void gotoxy(int x, int y)
{
    COORD dwPos;
    dwPos.X=x;
    dwPos.Y=y;

    SetConsoleCursorPosition(hCon, dwPos);
}

void setColor(int texto, int fondo)
{
    SetConsoleTextAttribute(hCon, fondo*16+texto);
}

void setBufferTamano(int ancho, int alto)
{
    COORD buffertamano = {ancho, alto};

    if(SetConsoleScreenBufferSize(hCon, buffertamano) == 0)
        std::cout << "ERROR de WinApi numero: " << GetLastError() << std::endl;
}

void setVentanaTamano(int ancho, int alto)
{
    SMALL_RECT ventanatamano1 ={0, 0, ancho-1, alto-1};
    SMALL_RECT* ventanatamano = &ventanatamano1;

    if(SetConsoleWindowInfo(hCon, TRUE, ventanatamano) == 0)
        std::cout << "ERROR de WinApi numero: " << GetLastError() << std::endl;
}

void setVentanaBufferTamano(int anchoVentana, int altoVentana, int anchoBuffer, int altoBuffer)
{
    setBufferTamano(anchoBuffer, altoBuffer);
    setVentanaTamano(anchoVentana, altoVentana);
}

int getPosCursorX()
{
    GetConsoleScreenBufferInfo(hCon, infoCon);

    return infoCon->dwCursorPosition.X;
}

int getPosCursorY()
{
    GetConsoleScreenBufferInfo(hCon, infoCon);

    return infoCon->dwCursorPosition.Y;
}

}

Thanks in advance!

Upvotes: 0

Views: 883

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409356

To solve this, instead of declaring infoCon as a pointer to a CONSOLE_SCREEN_BUFFER_INFO (the prefix P means that it's a pointer), declare it as the actual structure:

CONSOLE_SCREEN_BUFFER_INFO infoCon;

then use the address-of operator & when you need a pointer to it:

GetConsoleScreenBufferInfo(hCon, &infoCon);

To explain more, when you declare global variables, they are automatically initialized to zero by the compilers run-time system. And a pointer that is zero is the same as a NULL pointer. Dereferencing a NULL pointer leads to undefined behavior, which in many cases can cause crashes.

An important thing to know about undefined behavior, is that sometimes it can seem to work. Sometimes it seems to work flawlessly, other times it seems to work but produces unexpected result, but like I said before, most of the time the program just crashes.

Regarding the initialization of variables. Local (non-static) variables are not initialized at all. Using uninitialized local variables is also undefined behavior, and the value of an uninitialized local variate is indeterminate. If you check it it will be seemingly random. In reality, as all C compilers put local variables on the stack, the value will be what is in memory at the location of the variable. Local static variables which are uninitialized are, like global variables, initialized to zero.

Upvotes: 5

Related Questions