wifstream析构触发abort()调用错误:原因及修复方案(VS2017)
问题原因分析
这个abort()错误的根源在于**std::locale对传入的facet指针的所有权管理**:
你代码里的cv1是栈上分配的局部对象,当你把&cv1传给std::locale的构造函数时,默认情况下locale会认为这个指针是动态分配的,会取得它的所有权。当locale对象(包括inFile内部持有的locale副本)在函数结束时被销毁,它会尝试调用delete来释放这个指针——但栈内存根本不能用delete释放,VS的Debug堆检测到这个非法操作,就触发了abort()报错。
修复方案
有两种可靠的修复方式,根据你的需求选择:
方式一:动态分配facet,让locale接管所有权
这种方式最省心,不用操心生命周期问题,locale会自动负责销毁facet:
wifstream inFile; // 动态分配codecvt对象,让locale接管所有权 std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>* cv1 = new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>(); inFile.imbue(std::locale(inFile.getloc(), cv1)); return 0;
方式二:让locale不接管facet所有权(适用于栈上对象)
如果你想保持cv1在栈上分配,需要使用std::locale构造函数的重载,明确告诉它不要删除传入的指针:
wifstream inFile; std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian> cv1; // 第三个参数false表示locale不拥有该facet的所有权,不会delete它 inFile.imbue(std::locale(inFile.getloc(), &cv1, false)); return 0;
⚠️ 注意:这种方式下,cv1的生命周期必须至少和使用该locale的inFile一样长,否则会出现悬空指针问题。在你的代码里两者都是函数内的局部变量,生命周期一致,所以是安全的。
内容的提问来源于stack exchange,提问作者Woody20
相关产品推荐
相关产品推荐

