c++qtqtextstream

Why am I getting a crash using QTextStream on an open FILE *


I'm on windows, qt 4.7. part of my code takes a FILE* from a file which is open for reading by another part of the system (legacy, C). I open a QTextStream as follows:

// file currently opened (readonly), and partially read
FILE *infile = function_to_get_file_pointer(); 
QTextStream is(infile, QIODevice::ReadOnly);

The second line crashes when built in release mode but is fine in debug. I can step through the debug version and see the QFile that is opened internally by QTextStream. The most I've managed to get out of the windows call stack in release mode at the time of the crash is below:

ntdll.dll!77450226()    
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] 
ntdll.dll!77450142()    
msvcr80.dll!_lock_file(_iobuf * pf=0x71962148)  Line 241 + 0xa bytes    C
msvcr80.dll!_ftelli64(_iobuf * stream=0x71962148)  Line 51 + 0x8 bytes  C
QtCore4.dll!6708b87d()  
QtCore4.dll!67099294()  
QtCore4.dll!6713d491()  

which could be a red herring but look like something's gone wrong trying to lock the file. Prior to this, I have enabled debug output for my code so I know that it is the QTextStream creation that is causing the problem. I welcome any suggestions!

After some further digging, I have found that the file, although ASCII, is originally fopened with "rb" in order to stop the win32 CRT converting line endings from \r\n to \n. I assumed this would be confusing Qt so modified the fopen to use "r" only. Then a comment below linked to here which shows that the FILE* should be opened in binary mode, e.g. "rb", so this is not a problem.

Trying tezrigs suggestion below, freopen on the FILE* gives the following:

msvcr100.dll!_crt_debugger_hook(int _Reserved=8633404)  Line 65 C
    msvcr100.dll!_call_reportfault(int nDbgHookCode=2, unsigned long dwExceptionCode=3221226519, unsigned long dwExceptionFlags=1)  Line 167 + 0x6 bytes    C++
    msvcr100.dll!_invoke_watson(const wchar_t * pszExpression=0x00000000, const wchar_t * pszFunction=0x00000000, const wchar_t * pszFile=0x00000000, unsigned int nLine=0, unsigned int pReserved=8633376)  Line 155 + 0xf bytes   C++
    msvcr100.dll!_invalid_parameter(const wchar_t * pszExpression=0x00000000, const wchar_t * pszFunction=0x00000000, const wchar_t * pszFile=0x00000000, unsigned int nLine=0, unsigned int pReserved=0)  Line 110 + 0x14 bytes    C++
    msvcr100.dll!_invalid_parameter_noinfo()  Line 121 + 0xc bytes  C++
    msvcr100.dll!_freopen_helper(_iobuf * * pfile=0x0083bc3c, const char * filename=0x00000000, const char * mode=0x013ee350, _iobuf * str=0x71962148, int shflag=64)  Line 31 + 0x1f bytes C
    msvcr100.dll!freopen(const char * filename=0x00000000, const char * mode=0x013ee350, _iobuf * str=0x71962148)  Line 111 C

The exception code passed to _call_report_fault is 0x0000417 - Fatal Error: Unknown Software Exception, which isn't much help..

OK: more detail, and some self contained, replicable code (myfile.txt must be over 1000 chars long):

#include <QtCore/QCoreApplication>
#include "qtextstream.h"
#include <iostream>

int main(int argc, char *argv[])
{ 
 // QCoreApplication a(argc, argv);  
  std::cin.get();
  FILE *myfile = fopen("myfile.txt", "rb");

  int c;
  for(int i=0; i < 1000; i++)
    c = getc(myfile);
  fflush(myfile);
  long pos = ftell(myfile);

  QTextStream is(myfile, QIODevice::ReadOnly);
  while(!is.atEnd())
  {
     QString in_line = is.readLine();
     std::cout << in_line.toStdString();
  }
  fseek(myfile, pos, SEEK_SET);
  fclose(myfile);
  return 0;
}

All the following in release mode:

This lets me attach a debugger if I run outside visual studio. If I run in outside visual studio, it crashes. If I attach to it once it has started from outside visual studio, it crashes on construction of QTextStream. If I start it from inside visual studio with shift-F5 (i.e. running outside the debugger) it writes the contents of the file to the display. likewise, when running under the debugger, it works as expected.

It is down to the dlls. I have a locally compiled set of dlls (created with MSVC2010) and using them to replace those in the main product solves the problem. Ditto with the test code. The release code was using Qt compiled with 2005, using msvcr80.


Solution

  • All credit to @KarstenKoop - feel free to post your answer here. The problem was due to Qt dlls that were using msvcr80.dll while the rest of the application was compiled using visual studio 2010 and thus using msvcr100.dll

    This link explains the perils of mixing visual studio versions quite nicely