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

使用shared_ptr包装ncurses newwin返回的WINDOW*触发段错误原因

问题:用std::shared_ptr包装ncurses的WINDOW*触发段错误的原因

在项目中使用ncurses库时,newwin()函数返回WINDOW*裸指针,为避免使用裸指针尝试用std::shared_ptr包装后触发了段错误,以下是两段对比代码:

无段错误的正常代码

#include "ncurses.h"
#include <memory>
int main()
{
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    
    auto win = newwin(10,10,0,0);
    //std::shared_ptr<WINDOW> sh_ptr = std::make_shared<WINDOW>(*win);
    //auto win1 = sh_ptr.get();
    
    mvwaddstr(win,0,2, "hello");
    wrefresh(win);
    getch();

    endwin();
    return 0;
}

触发段错误的代码

#include "ncurses.h"
#include <memory>
int main()
{
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    
    auto win = newwin(10,10,0,0);
    std::shared_ptr<WINDOW> sh_ptr = std::make_shared<WINDOW>(*win);
    auto win1 = sh_ptr.get();
    
    mvwaddstr(win1,0,2, "hello");
    wrefresh(win1);
    getch();

    endwin();
    return 0;
}

原因分析

  1. 错误的对象复制操作
    std::make_shared<WINDOW>(*win)本质是对newwin返回的WINDOW对象做了值拷贝,生成了一个完全独立的新WINDOW实例,而非共享原有的窗口资源。ncurses的WINDOW内部绑定了终端底层资源(比如屏幕缓冲区、终端状态关联信息),这个拷贝出来的新对象不被ncurses内部管理系统认可,当用mvwaddstr、wrefresh这类函数操作它时,会访问无效内存区域,直接触发段错误。

  2. shared_ptr的使用逻辑错误
    std::make_shared的设计目的是创建新对象并托管其指针,而非接管已存在的外部资源(比如ncurses通过newwin创建的窗口)。此外,ncurses的窗口资源不能用C++默认的delete销毁,必须用ncurses提供的delwin()函数,所以即使要托管原指针,也需要给shared_ptr指定自定义删除器。


正确的用法示例

#include "ncurses.h"
#include <memory>

int main()
{
    initscr();
    cbreak();
    noecho();
    keypad(stdscr, TRUE);
    
    // 直接托管newwin返回的指针,同时指定自定义删除器delwin
    std::shared_ptr<WINDOW> sh_ptr(newwin(10,10,0,0), delwin);
    
    mvwaddstr(sh_ptr.get(), 0, 2, "hello");
    wrefresh(sh_ptr.get());
    getch();

    endwin();
    return 0;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 15:43:09