Chinaunix

标题: Debugging Ncurses Programs [打印本页]

作者: hongst    时间: 2009-04-02 12:10
标题: Debugging Ncurses Programs
Activities like printing characters to a screen, moving the cursor, and changing the color of character output are collectively known as screen handling. By its nature, screen handling is very terminal dependent, however, the terminfo and termcap mechanisms were devised to provide terminal independent screen handling. The
curses
library (a pun on the term "cursor optimization") was created to provide a screen handling API for C programmers. The goal of curses was to provide a fast, portable, and terminal independent C API to handle device dependent terminal codes.
Curses has a very long and twisted history. However, the most commonly used modern implementation of the library is called new curses, or
ncurses
, for short, which is maintained by
Thomas E. Dickey
. Ncurses is a GNU project released under an MIT style licence and is used under nearly all modern Unixes including GNU/Linux, and Mac OS X. There are now many extensions to ncurses which includes panels, menus and even a full featured widget set: the
Curses Development Kit
(CDK).
Getting Started
To follow along, download
ncurses1
.
1   // ncurses1.c
2   #include
3   #include
4   #include
5   
6   unsigned int Seeder(void);
7   int Irand(int low, int high);
8   void Print_A_Character(void);
9   
10  int main(void)
11  {
12       atexit( (void *)endwin );
13       initscr();
14       Seeder();
15  
16       for (int i = 0; i
Compile and run the program. It should fill your console (or xterm) with characters. It has a bug though: the top row and first column seem to be devoid of characters:


Since the probability of that happening is miniscule (and gets smaller with each passing second), there must be a bug in the program.
You need to do a bit more to use GDB with a program that uses ncurses. The problem is that GDB's I/O is intermixed with the program's I/O. Once you get used to it, this is not normally a problem. But when the program performs screen handling, it becomes difficult, if not impossible, to keep track of your debugging session. To see this in action, start GDB on the executable, set a breakpoint at Print_A_Character(), and run the program.
   $ gdb debugging_ncurses
   (gdb) break Print_A_Character
   Breakpoint 1 at 0x80486fd: file debugging_ncurses.c, line 26.
   (gdb) run
   Starting program: code/ncurses/debugging_ncurses
   
   Breakpoint 1, Print_A_Character () at debugging_ncurses.c:26
   26              int x = Irand(1, COLS);
Now issue continue 50 a few times. You should see a big mess. Here's what I see:


Quit GDB when you've had enough. Clearly, we need a way to separate GDB's I/O from the program's I/O when screen handling is done.
Separating the Input/Output
You'll need two terminals (either two consoles or two xterms): One for the program's I/O and another for GDB's I/O. Separating out the two I/O will resolve the problem nicely. I'll be using the word `xterm', but the same thing applies to all non-login terminals like rxvt and eterm, and login terminals like virtual consoles.
  • Go to the first xterm and find its device file using either tty or who am i. This will be the xterm with GDB's I/O.:    $ tty
       /dev/pts/1
       $ who am i
       p        pts/1        May 26 12:44 (:0.0)
  • Go to the second xterm and find its device file. This will be the xterm with our program's I/O:    $ tty
       /dev/pts/4
  • Go back to the first xterm and start a debugging session. Set a breakpoint at Print_A_Character().    $ gdb debugging_ncurses
       (gdb) break Print_A_Character
       Breakpoint 1 at 0x80486fd: file debugging_ncurses.c, line 26.
       (gdb)
  • GDB's tty command instructs GDB to redirect the program's I/O to another terminal. The argument to tty is the device file of the terminal you wish the program I/O to go. In this case, I want the program's I/O to go to the second xterm, pts/4. If you're following along, use whatever device file you obtained in step 2:    (gdb) tty /dev/pts/4
       (gdb)
  • Lastly, go to the second xterm (that contains the program's I/O) and tell the shell to sleep for a long time. This is so that anything we type in that window will be sure to go to our program rather than the shell. The amount of time is arbitrary, but pick a time that's longer than you suspect the debugging session will last. This tells the shell to "do nothing" for 100000 seconds:    $ tty
       /dev/pts/4
       $ sleep 100000
  • Go back to the first xterm which is running GDB and debug to your heart's content. When you're done, you can go back to the program output window and slap it with a control-c to break out of the sleep.
    Debugging Ncurses Example
    Let's go through a sample debugging session of debugging_ncurses.c. The problem was that the first row and column aren't being printed to. At first guess, we might suspect that the random number generator is at fault.


    本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/11786/showart_1888460.html




    欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2