c - C 中的 ncurses 打印的内容超出应有的内容并打印颜色代码

标签 c thread-safety ncurses

当我尝试使用 mvwprintfncurses 窗口中打印一些值时,它有时会在预期打印的内容之后打印额外的字符,就像它正在读取一样旧内存。然而,这种情况不应该发生,因为要打印的值预先经过 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;
}

最佳答案

问题出在线程的使用上。 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.solibncurseswt.so,它具有与 ncurses/ncursesw 不同的二进制接口(interface)。 “大多数”程序无需更改源代码即可编译和运行;全局变量有“getter”函数,例如LINES,它们(在可能的情况下)作为宏实现,以帮助在不同类型的库之间进行移植。

关于c - C 中的 ncurses 打印的内容超出应有的内容并打印颜色代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30786013/

相关文章:

C++ Int 位操作是 2UL = 10UL?

c - 在我们的 C/C++ 程序中使用 espeak 需要哪些行?

c++ - 在这种情况下如何使 shared_ptr 线程安全?

c - Ncurses 和文本框

c - 带有 WSL 的 NCurses 显示框不正确

c++ - 用 C/C++ 代码中的定义替换所有函数调用

c - 如何写条件运算符(?:) without using else

Ruby 暂停线程

java - 为什么这段代码不是线程安全的,即使在使用同步方法时也是如此?

c++ - 使用 C++ 更改终端字体大小