You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

添加-lncurses后G++仍无法链接ncurses问题求助

问题:g编译调用ncurses的C程序出现链接错误,clang++可正常编译

我用g编译调用ncurses库的C程序时,出现链接错误,提示initscr、cbreak等ncurses函数未定义,但用clang++编译能正常通过。我已经通过源码安装了ncurses,且确认库可用。以下是编译报错信息、Makefile及代码,求解决链接问题。

编译报错输出

CC  main.cpp ./main
main.cpp: In function ‘int main(int, char**)’:
main.cpp:34:34: warning: format not a string literal and no format arguments [-Wformat-security]
   34 |  wprintw(window_one, text.c_str());
      |                                  ^
main.cpp:38:34: warning: format not a string literal and no format arguments [-Wformat-security]
   38 |  wprintw(window_two, text.c_str());
      |                                  ^
/usr/bin/ld: /tmp/cct3HGZR.o: in function `main':
/home/ubuntu/side-projects/slides/main.cpp:13: undefined reference to `initscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:14: undefined reference to `cbreak'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:16: undefined reference to `stdscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:16: undefined reference to `keypad'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:18: undefined reference to `start_color'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:19: undefined reference to `init_pair'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:21: undefined reference to `stdscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:21: undefined reference to `wbkgd'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:23: undefined reference to `LINES'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:24: undefined reference to `COLS'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:27: undefined reference to `printw'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:28: undefined reference to `refresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:33: undefined reference to `wmove'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:34: undefined reference to `wprintw'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:35: undefined reference to `wrefresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:37: undefined reference to `COLS'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:37: undefined reference to `COLS'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:37: undefined reference to `LINES'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:38: undefined reference to `wprintw'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:39: undefined reference to `wrefresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:41: undefined reference to `stdscr'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:41: undefined reference to `wgetch'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:45: undefined reference to `endwin'
/usr/bin/ld: /tmp/cct3HGZR.o: in function `create_newwin(int, int, int, int)':
/home/ubuntu/side-projects/slides/main.cpp:52: undefined reference to `newwin'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:53: undefined reference to `box'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:55: undefined reference to `wrefresh'
/usr/bin/ld: /tmp/cct3HGZR.o: in function `destroy_win(_win_st*)':
/home/ubuntu/side-projects/slides/main.cpp:60: undefined reference to `wborder'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:61: undefined reference to `wrefresh'
/usr/bin/ld: /home/ubuntu/side-projects/slides/main.cpp:62: undefined reference to `delwin'
collect2: error: ld returned 1 exit status
make: *** [Makefile:9: all] Error 1

Makefile内容

CC = g++
CFLAGS = -g -lncurses -Wall
SRC = main.cpp
OUT = ./main

.PHONY: all
all: ${SRC}
        @echo "CC " ${SRC} ${OUT}
        @${CC} ${CFLAGS} ${SRC} -o ${OUT}
        @echo "Done"

.PHONY: clean
clean:
        @echo "Cleaning Directory"
        @rm -rf ${OUT}
        @echo "Done"

C++代码

#include <ncurses.h>
#include <string>

WINDOW *create_newwin(int height, int width, int starty, int startx);
void destroy_win(WINDOW *local_win);

int main(int argc, char *argv[]) {
        WINDOW *window_one;
        WINDOW *window_two;
        int startx, starty, width, height;
        int ch;

        initscr();
        cbreak();

        keypad(stdscr, TRUE);

        start_color();
        init_pair(1, COLOR_BLUE, COLOR_RED);

        bkgd(COLOR_PAIR(1));

        height = LINES;
        width = COLS / 2;
        starty = 0;
        startx = 0;
        printw("Press F1 to exit");
        refresh();
        window_one = create_newwin(height, width, starty, startx);

        std::string text = "test";

        wmove(window_one, height / 2, text.size() / 2);
        wprintw(window_one, text.c_str());
        wrefresh(window_one);

        window_two = create_newwin(LINES, COLS / 2, 0, COLS / 2);
        wprintw(window_two, text.c_str());
        wrefresh(window_two);

        while((ch = getch()) != KEY_F(1)) {
                switch(ch) {}
        }

        endwin();
        return 0;
}

WINDOW *create_newwin(int height, int width, int starty, int startx) {
        WINDOW *local_win;

        local_win = newwin(height, width, starty, startx);
        box(local_win, 0, 0);

        wrefresh(local_win);
        return local_win;
}

void destroy_win(WINDOW *local_win) {
        wborder(local_win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
        wrefresh(local_win);
        delwin(local_win);
}

解决方案

问题根源

g和clang在处理链接库参数的顺序上有差异:链接库参数-lncurses必须放在源文件/目标文件之后。你的Makefile里把-lncurses放在了CFLAGS中,编译时会先于源文件main.cpp被处理,导致g无法正确找到ncurses库中的符号;而clang对参数顺序的容错性更高,所以能正常编译。

另外,源码安装的ncurses可能不在系统默认的库搜索路径中,需要额外指定头文件和库的路径。

修复步骤

  1. 调整Makefile的参数顺序:
    将链接库参数从CFLAGS中分离出来,单独用LDFLAGS存放,并且编译时将LDFLAGS放在源文件之后。如果是源码安装的ncurses,还需要添加-I指定头文件路径(比如/usr/local/include),-L指定库路径(比如/usr/local/lib)。

    修改后的Makefile:

    CC = g++
    CFLAGS = -g -Wall
    # 如果源码安装的ncurses不在默认路径,取消下面两行注释
    # INCLUDES = -I/usr/local/include
    # LDFLAGS = -L/usr/local/lib -lncurses
    # 如果是系统默认路径,直接用下面的LDFLAGS
    LDFLAGS = -lncurses
    SRC = main.cpp
    OUT = ./main
    
    .PHONY: all
    all: ${SRC}
            @echo "CC " ${SRC} ${OUT}
            @${CC} ${CFLAGS} ${INCLUDES} ${SRC} -o ${OUT} ${LDFLAGS}
            @echo "Done"
    
    .PHONY: clean
    clean:
            @echo "Cleaning Directory"
            @rm -rf ${OUT}
            @echo "Done"
    
  2. 验证库路径(可选):
    如果源码安装后还是找不到库,可以用ncursesw-config --cflags --libs命令获取正确的编译和链接参数,替换到Makefile中:

    # 执行该命令会输出类似内容:
    # -I/usr/local/include/ncursesw -L/usr/local/lib -lncursesw
    

    把输出的参数分别对应到INCLUDES和LDFLAGS中即可。

  3. 解决格式安全警告(可选):
    编译时的-Wformat-security警告,是因为wprintw需要格式字符串。可以把代码中的wprintw(window_one, text.c_str());改为wprintw(window_one, "%s", text.c_str());,消除警告。


内容的提问来源于stack exchange,提问作者boomcreeper11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 07:05:24