C中的ncurses打印得比应有的多,并打印颜色代码

时间:2015-06-11 16:09:40

标签: c thread-safety ncurses

当我尝试在ncurses窗口中使用mvwprintf打印某些值时,它有时会在预期打印之后打印额外的字符,就好像它正在读取旧内存一样。但是,这不应该发生,因为要打印的值是strdup - 事先编辑,并且应该只包含一个字符和NUL来终止字符串。

使用带有start_color()后跟init_pairattron(COLOR_PAIR(n))来电的颜色时会出现错误,其中打印颜色代码,但显然不应该。

Screenshot

我在Google上找不到与此相关的任何内容,所以我希望有人可以在那里找到错误。

这是在两级for循环中,其中print_tile返回单个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;
}

1 个答案:

答案 0 :(得分:1)

问题在于使用线程。 curses / ncurses在静态变量中维护状态,并且通常不是线程安全的。 ncurses 可以编译为减少静态变量的使用,如 PORTABILITY 上的手册页部分所述:

  

可以将此实现配置为为多线程应用程序提供基本支持。有关详细信息,请参阅curs_threads(3x)

当它像这样编译时(使用--with-pthread选项),会构建一个具有不同名称的库,例如libncursest.solibncurseswt.so,它具有不同的二进制接口。 ncurses的/ ncursesw。 “大多数”程序可以在没有源更改的情况下编译和运行;有LINES等全局变量的“getter”函数,它们(如果可能的话)实现为宏,以帮助在不同类型的库之间移植。