C 中的 ncurses 打印的内容超出应有的范围,并打印颜色代码
ncurses in C prints more than it should and prints colour codes
当我尝试使用 mvwprintf
在 ncurses
window 中打印一些值时,它有时会在预期打印的内容之后打印额外的字符,就好像它正在阅读一样旧记忆。然而,这不应该发生,因为要打印的值是预先 strdup
-ed 并且应该只包含一个字符和一个 NUL
来终止字符串。
当使用带有 start_color()
的颜色后跟 init_pair
和 attron(COLOR_PAIR(n))
调用时,也会发生错误,其中打印了颜色代码,但显然不应该。
我在 Google 上找不到与此相关的任何内容,所以我希望有人能找到其中的错误。
这是一个两级 for
循环,其中 print_tile
returns 一个 char
.
// Convert the tile to a character to print
char str[2] = { print_tile(map.tiles[y][j]), 0 };
int colour = tile_colour(map.tiles[y][j]);
// Queue the character up for displaying
Vector2 pos = { x, y };
add_to_queue(display_queue, window, str, pos, colour);
这会向显示队列添加一个项目:
void add_to_queue(Queue *queue, WINDOW *window, char *value, Vector2 coords, int colour)
{
DisplayItem *item = malloc(sizeof(DisplayItem));
item->window = window;
item->value = strdup(value);
item->coords = coords;
item->colour = colour;
pthread_mutex_lock(&mutex);
push(queue, item);
pthread_mutex_unlock(&mutex);
}
这实际上打印了队列中的当前项目:
void* display(void *arg)
{
Queue *queue = arg;
while (1) {
// Wait to receive an item to display
while (queue->size == 0);
pthread_mutex_lock(&mutex);
DisplayItem *item = queue_item(take(queue), DisplayItem);
// Exit when receiving the exit message
if (strcmp(item->value, DISP_QUIT) == 0)
break;
// Process the current message in the queue
wattron(item->window, COLOR_PAIR(item->colour));
mvwprintw(item->window, item->coords.y, item->coords.x, item->value);
wrefresh(item->window);
wattroff(item->window, COLOR_PAIR(item->colour));
free(item);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
问题出在线程的使用上。 curses/ncurses 在静态变量中维护状态,通常不是线程安全的。 ncurses 可以编译为减少静态变量的使用,如PORTABILITY的手册页部分所述:
This implementation can be configured to provide rudimentary support for multi-threaded applications. See curs_threads(3x) for details.
像这样编译时(使用--with-pthread
选项),会生成一个不同名称的库,例如libncursest.so
或libncurseswt.so
,它有不同的二进制文件界面比ncurses/ncursesw。 "Most" 程序可以编译并且 运行 无需更改源代码;全局变量有 "getter" 函数,例如 LINES
,它们(在可能的情况下)作为宏实现,以帮助在不同类型的库之间进行移植。
当我尝试使用 mvwprintf
在 ncurses
window 中打印一些值时,它有时会在预期打印的内容之后打印额外的字符,就好像它正在阅读一样旧记忆。然而,这不应该发生,因为要打印的值是预先 strdup
-ed 并且应该只包含一个字符和一个 NUL
来终止字符串。
当使用带有 start_color()
的颜色后跟 init_pair
和 attron(COLOR_PAIR(n))
调用时,也会发生错误,其中打印了颜色代码,但显然不应该。
我在 Google 上找不到与此相关的任何内容,所以我希望有人能找到其中的错误。
这是一个两级 for
循环,其中 print_tile
returns 一个 char
.
// Convert the tile to a character to print
char str[2] = { print_tile(map.tiles[y][j]), 0 };
int colour = tile_colour(map.tiles[y][j]);
// Queue the character up for displaying
Vector2 pos = { x, y };
add_to_queue(display_queue, window, str, pos, colour);
这会向显示队列添加一个项目:
void add_to_queue(Queue *queue, WINDOW *window, char *value, Vector2 coords, int colour)
{
DisplayItem *item = malloc(sizeof(DisplayItem));
item->window = window;
item->value = strdup(value);
item->coords = coords;
item->colour = colour;
pthread_mutex_lock(&mutex);
push(queue, item);
pthread_mutex_unlock(&mutex);
}
这实际上打印了队列中的当前项目:
void* display(void *arg)
{
Queue *queue = arg;
while (1) {
// Wait to receive an item to display
while (queue->size == 0);
pthread_mutex_lock(&mutex);
DisplayItem *item = queue_item(take(queue), DisplayItem);
// Exit when receiving the exit message
if (strcmp(item->value, DISP_QUIT) == 0)
break;
// Process the current message in the queue
wattron(item->window, COLOR_PAIR(item->colour));
mvwprintw(item->window, item->coords.y, item->coords.x, item->value);
wrefresh(item->window);
wattroff(item->window, COLOR_PAIR(item->colour));
free(item);
pthread_mutex_unlock(&mutex);
}
return NULL;
}
问题出在线程的使用上。 curses/ncurses 在静态变量中维护状态,通常不是线程安全的。 ncurses 可以编译为减少静态变量的使用,如PORTABILITY的手册页部分所述:
This implementation can be configured to provide rudimentary support for multi-threaded applications. See curs_threads(3x) for details.
像这样编译时(使用--with-pthread
选项),会生成一个不同名称的库,例如libncursest.so
或libncurseswt.so
,它有不同的二进制文件界面比ncurses/ncursesw。 "Most" 程序可以编译并且 运行 无需更改源代码;全局变量有 "getter" 函数,例如 LINES
,它们(在可能的情况下)作为宏实现,以帮助在不同类型的库之间进行移植。