Прервать в деструкторе

Следующий код C++ получает загадочную ошибку ("Ошибка отладки!... вызвана abort()"), когда return выполнен. Это Visual Studio 2017 15.6.3, и программа представляет собой отладочную 64-битную сборку, работающую под 64-битной Windows 7. Что является причиной этой ошибки и как ее исправить?

wifstream inFile;

std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian> cv1;
inFile.imbue(std::locale(inFile.getloc(), &cv1));
return 0;

Трассировка с помощью отладчика показывает, что сообщение исходит из инструкции дизассемблера

call        std::basic_ifstream<wchar_t,std::char_traits<wchar_t> >::`vbase destructor'

Последняя запись в стеке, кроме msvcp140d.dll, vcruntime140d.dll а также ucrtbased.dll является

    MyApp.exe!std::basic_ifstream<wchar_t,std::char_traits<wchar_t> >::`vbase destructor'() C++

Целью этого кода является входной файл infile Unicode (little-endian), и я читаю его в std::string переменная.

1 ответ

Решение

std::locale поддерживает счетчик ссылок для каждого фасета, который связан с ним. std::locale конструктор, который вы вызываете, будет увеличивать счетчик ссылок для std::codecvt_utf16 объект, который вы передаете, а затем std::locale Деструктор уменьшит этот счетчик ссылок. Когда счетчик ссылок std::codecvt_utf16 падает до 0, он будет уничтожен через delete оператор. Вот почему вы получаете ошибку прерывания - когда std::wifstream деструктор убирает imbue Деструктор локали пытается delete то, что не было выделено с new оператор для начала.

Сделайте это вместо этого:

inFile.imbue(std::locale(inFile.getloc(),
    new std::codecvt_utf16<wchar_t, 0x10ffff, std::little_endian>));

Смотрите пример в std::codecvt_utf16 документация на http://en.cppreference.com/.

Другие вопросы по тегам