4

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.

mike
  • 1,192
  • 9
  • 32
  • You should compile in debug mode to get a useful stack trace. – Tamás Szelei May 10 '16 at 10:41
  • if you read the question, I don't see the behaviour in debug mode – mike May 10 '16 at 10:43
  • On the error said that you are missing ntdll.dll. Have you double check, if this available on your machine? Another possible is you have ntdll.dll but the version is not suitable which lead to missing method name. – Apin May 10 '16 at 10:55
  • 1
    ` FILE *infile = function_to_get_file_pointer(); infile = freopen ( NULL, "rb", infile); QTextStream is(infile, QIODevice::ReadOnly); ` – Tezirg May 10 '16 at 10:56
  • 2
    Innards of `function_to_get_file_pointer()` might clarify the picture. Can you verify that it returns a valid file pointer? Try calling `ftell` on it yourself, would it crash? – n. m. could be an AI May 10 '16 at 10:57
  • @mike, sorry, I missed that part. Still you should then generate debug symbols for the release build, because no one will guess the function names from the offsets. – Tamás Szelei May 10 '16 at 10:59
  • @ n.m regarding function_to_get_file_pointer. There's a struct based file reading system which has as part of its root the FILE* of the file. this pointer is returned directly. I can definitely ftell the FILE * no problem in release mode. – mike May 10 '16 at 11:00
  • @tamas no worries :-) I have done that for my code, but it would require recompiling Qt to get a decent stack trace in release, which I would really prefer not to have to do. – mike May 10 '16 at 11:02
  • @apin I think this is just telling me that it hasn't loaded debug symbols for ntdll.dll. If I had an issue with that dll it would have manifested elsewhere – mike May 10 '16 at 11:03
  • @tezirg, this looks promising - its currently crashing trying to do the freopen which may point me in a useful direction.. – mike May 10 '16 at 11:26
  • 1
    @mike I had the hint when looking at this http://doc.qt.io/qt-4.8/qfile.html#open-4. There is a special windows users section – Tezirg May 10 '16 at 11:54
  • @tezirg - turns out that it already is opened rb, so I'm no closer – mike May 10 '16 at 12:27
  • 1
    Can you try to fflush before cosntructing the QTextStream ? – Tezirg May 10 '16 at 12:42
  • @Tezirg - no change when I use fflush, good idea though – mike May 10 '16 at 12:55
  • New ideas : 1 - can you try to add a scope before the function_to_get_file_pointer call ? 2 - Can you look at the stack trace using the debug mode ? – Tezirg May 10 '16 at 14:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/111539/discussion-between-tezirg-and-mike). – Tezirg May 10 '16 at 14:01
  • 1
    I see both msvcr80.dll and msvcr100.dll, could this be a version conflict between those two? – Karsten Koop May 10 '16 at 14:16
  • @KarstenKoop you may be onto something here. I've tried just opening a fresh FILE * and passing it to QTextStream (much earlier in the code) and that fails as per the other calls, in release mode. – mike May 10 '16 at 15:16

1 Answers1

1

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

mike
  • 1,192
  • 9
  • 32