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

C语言ncurses中set_menu_format的row参数是否存在硬性限制?

set_menu_format的row参数是否存在硬性限制?

我正在编写一个基于菜单的C语言ncurses程序,已确保set_menu_format的row参数小于子窗口尺寸,但无法将row参数设置为大于21的值。通过getmaxyx获取到终端的最大行数为35,当row参数超过21时,程序会抛出“free(): invalid pointer”错误并出现“zsh: IOT instruction(core dumped)”核心转储。

相关代码片段

核心问题代码

set_menu_win(my_menu, my_menu_win[0]);
set_menu_sub(my_menu, derwin(my_menu_win[0],29,(ncols/3)-2,1,1));
set_menu_format(my_menu, 21, 1);

菜单遍历函数

void traverse(MENU *my_menu,WINDOW **my_menu_win,ITEM **my_items,int argc) {
    int c,cur_win_index=0;
    while((c=getch()) != 'q') {
        ITEM *cur_item = current_item(my_menu);
        switch(c) {
            case 'j':
                if(cur_item == my_items[argc-2])
                    menu_driver(my_menu, REQ_FIRST_ITEM);
                else
                    menu_driver(my_menu, REQ_DOWN_ITEM);
                break;

            case 'k':
                if(cur_item == my_items[0])
                    menu_driver(my_menu, REQ_LAST_ITEM);
                else
                    menu_driver(my_menu, REQ_UP_ITEM);
                break;
        }
        wrefresh(my_menu_win[0]);
    }
}

菜单显示函数

void menu_display(int argc, char *argv[]) {
    // Declaration //
    ITEM **my_items;
    MENU *my_menu;
    WINDOW *my_menu_win[3], *title_win;
    PANEL *my_panels[3];
    
    char store[argc-1][4];
    int c,i;
    char search;
    int nlines,ncols,startx,starty;
    // Declaration //

    // Initialize curses //
    initscr();
    start_color();
    cbreak();
    noecho();
    curs_set(0);
    keypad(stdscr,TRUE);
    init_pair(1, COLOR_RED, COLOR_BLACK);
    // Initialize curses //

    // Initialize Variables //
    getmaxyx(stdscr, nlines, ncols);
    starty = 0;
    startx = 0;
    // Initialize Variables //


    // Create Menu Items //
    my_items = (ITEM **)calloc(argc, sizeof(ITEM *));
   
    for(i=1;i<argc;i++)  {
        sprintf(store[i-1],"%d",i);
        my_items[i-1] = new_item(store[i-1], argv[i]);
    }
    my_items[argc] = (ITEM *)NULL;
    // Create Menu Items //

    
    // Create Menu //
    my_menu = new_menu((ITEM**)my_items);
    // Create Menu //
   

    // Create windows and panels //
    title_win = newwin(2, ncols, starty, startx);

    my_menu_win[0] = newwin(30,ncols/3,starty+3,startx);
    my_menu_win[1] = newwin(30,ncols/3,starty+3,startx+(ncols/3));
    my_menu_win[2] = newwin(30,ncols/3,starty+3,3*startx+(2*ncols/3));
   
    for(i=0;i<3;i++)
        my_panels[i] = new_panel(my_menu_win[i]);
    // Create windows and panels //


    // sets menu main and sub windows ; sets menu mark//
    set_menu_win(my_menu, my_menu_win[0]);
    set_menu_sub(my_menu, derwin(my_menu_win[0],29,(ncols/3)-2,1,1));
    set_menu_format(my_menu, 21, 1);

    set_menu_mark(my_menu, "*"); // mark strings to show selected items
    // sets menu main and sub windows ; sets menu mark//
     
  
    // Print border around main window; add title//
    print_title(title_win, 1, startx, ncols, "File Manager", COLOR_PAIR(1));
    mvwprintw(title_win, 0, 0, "%d %d", nlines, ncols);
    
    for(i=0;i<3;i++)
        box(my_menu_win[i], 0, 0);
    // Print border around main window and title //
   
    
    // Refresh title window//
    wrefresh(title_win);
    // Refresh title window//


    // Post the menu; refresh panels //
    post_menu(my_menu);
    update_panels();
    doupdate();
    // Post the menu; refresh panels //

    
    // Traverse Menu Items //
    traverse(my_menu, my_menu_win, my_items, argc); 
    // Traverse Menu Items //
   
    
    // Free memory //
    unpost_menu(my_menu);
    free_menu(my_menu);
    for(i=0;i<argc;i++)
        free_item(my_items[i]);

    endwin();
    // Free memory //

}

问题分析与解决方案

set_menu_format本身没有硬性的row参数上限,它的限制仅来自于你设置的菜单子窗口尺寸(子窗口必须能容纳指定的行数和列数)。你的崩溃问题并非参数限制导致,而是内存越界和无效指针访问引发的。

关键问题点

  1. 菜单项数组越界
    你分配了argc个指针的数组my_items,但仅初始化了my_items[0]到my_items[argc-2](共argc-1个项),却直接将my_items[argc]设为NULL,跳过了my_items[argc-1]。这个未初始化的垃圾指针会导致后续菜单操作访问无效内存。

  2. 内存释放错误
    释放菜单项时,循环遍历0到argc-1,但实际有效的菜单项只有argc-1个(索引0到argc-2)。尝试释放my_items[argc-1]这个未初始化的指针,直接触发“free(): invalid pointer”错误,也就是你看到的崩溃。

修复步骤

  1. 修正菜单项终止标记
    将my_items[argc] = (ITEM *)NULL;改为my_items[argc-1] = (ITEM *)NULL;,确保数组终止符位置正确。

  2. 调整内存释放范围
    将释放循环改为:

    for(i=0;i<argc-1;i++)
        free_item(my_items[i]);
    

    只释放实际创建的菜单项,避免访问无效指针。

  3. 验证子窗口可用空间
    确认子窗口的实际可用行数:你创建的子窗口高度为29,去掉上下边框后实际可用行数为27,因此set_menu_format的row参数设为22及以下都是符合要求的,修正内存问题后即可正常使用更大的row值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 19:44:56