Search code examples
c++consolefstream

fstream declaration exception after hardclosing console / c++


I stumbled upon the following problem:

#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <Windows.h>

using namespace std;

class TestClass
{
public:
    ~TestClass();
};

TestClass::~TestClass()
{
    fstream f;
}

TestClass test;

int _tmain(int argc, _TCHAR* argv[])
{
    Sleep(10000);
}

This is a simple example so that you can reproduce my error. Everything works fine until I close console window manually (by pressing X in the console corner) while Sleep. Access Violation Exception is thrown at the

fstream f;

line in destructor. Is there any way to use fstream after manual console closing? Or i'm doing something totally wrong?

UPD:

Stack looks like this:

msvcp120d.dll!std::ctype<char>::widen(char _Byte) Line 2418

msvcp120d.dll!std::basic_ios<char,std::char_traits<char> >::widen(char _Byte) Line 129

msvcp120d.dll!std::basic_ios<char,std::char_traits<char> >::init(std::basic_streambuf<char,std::char_traits<char> > * _Strbuf, bool _Isstd) Line 170

msvcp120d.dll!std::basic_istream<char,std::char_traits<char> >::basic_istream<char,std::char_traits<char> >(std::basic_streambuf<char,std::char_traits<char> > * _Strbuf, bool _Isstd) Line 48

msvcp120d.dll!std::basic_iostream<char,std::char_traits<char> >::basic_iostream<char,std::char_traits<char> >(std::basic_streambuf<char,std::char_traits<char> > * _Strbuf) Line 954

ConsoleApplication6.exe!std::basic_fstream<char,std::char_traits<char> >::basic_fstream<char,std::char_traits<char> >() Line 1133

ConsoleApplication6.exe!TestClass::~TestClass() Line 19

Solution

  • According to this stack trace, the problem is indeed from a call from fstream's constructor: ios_base::init() initializes some variable with widen(' '), which calls ctype::widen on what is probably a null or destroyed ctype object (returned by use_facet), which causes a crash when it tries to call a virtual member function.

    Conclusion: some vital objects in the CRT are destroyed before your TestClass object is, therefore you can't use CRT types in your global destructor.