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

