Search code examples
cpointersmemorymemory-leakscurses

Why does arbitrary keyboard input change other memory in c, curses?


I am experimenting with Curses in C, and for some reason, when I enter a key when running my program the ball changes direction. I have no idea why; could this be a memory leak? I don't know what to try, since I am a beginner to C. Please provide any guidance that you have!

#include <curses.h>
#include <stdbool.h>

typedef struct ball {
    unsigned int x;
    unsigned int y;
    const char shape;
} Ball;

int main() {
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
curs_set(FALSE);
nodelay(stdscr, TRUE);

int maxY, maxX;
int pOneGoingRight = TRUE;
int pOneGoingDown = TRUE;
getmaxyx(stdscr, maxY, maxX);
char input;

Ball pOneBall = {0, 0, '*'};
// Ball *pOneBallPtr = &pOneBall;

while (1) {
    clear();
    
    getstr(&input);
    if (input == 'q')
        break;
    
    mvprintw(0, 0, "Max y and x: %d, %d", maxY, maxX); 
    mvprintw(1, 0, "Ball y and x: %d, %d", pOneBall.y, pOneBall.x);
    
    if (pOneBall.y == 0) pOneGoingDown = TRUE; 
    else if (pOneBall.y == maxY) pOneGoingDown = FALSE;
    
    if (pOneBall.x == 0) pOneGoingRight = TRUE; 
    else if (pOneBall.x == maxX) pOneGoingRight = FALSE;
    
    if (pOneGoingRight) pOneBall.x++;
    else pOneBall.x--;
    
    if (pOneGoingDown) pOneBall.y++;
    else pOneBall.y--;
    
    mvprintw(pOneBall.y, pOneBall.x, &pOneBall.shape);
    refresh();
    
    napms(100);

}

endwin();
return 0;
}

Solution

  • Just looking at your code

    char input;
    
    Ball pOneBall = {0, 0, '*'};
    

    Okay, so you have an input to hold the key, and then a struct to hold ball data.

    Then you call

    getstr(&input);
    

    From the manual

    The function getstr is equivalent to a series of calls to getch, until a newline or carriage return is received (the terminating character is not included in the returned string). The resulting value is placed in the area pointed to by the character pointer str.

    That means that getstr is reading from the keyboard until newline or carriage return is read. There's nothing to stop it from reading 10 characters, or a hundred, and writing them right over the data that follows, being your ball position info.

    Use getch if you want to read a single character, or some other method. Since there doesn't seem to be any way to limit how many characters getstr reads, just never use it. Ever.

    edit: try getnstr( &input, 1 ) maybe?

    edit-edit: that will beep on excess characters, which you probably don't want. just change to use getch or something