Почему `_getstream` потерпит неудачу? - PullRequest
1 голос
/ 06 ноября 2008

В исключении упоминается

FILE* __cdecl _getstream

Я звоню fopen, и он продолжает падать.

AfxMessageBox("getting here 1");
FILE* filePtr = fopen(fileName, "rb");
AfxMessageBox("getting here 2");

Почему-то я никогда не попадаю во второе окно сообщения. Интересно, что когда я нахожусь в режиме отладки, приложение работает отлично. Почему?

Ответы [ 4 ]

2 голосов
/ 07 ноября 2008

Я думаю, что повреждение памяти. В Windows (которую __cdecl заставляет меня думать, что вы используете) существует утилита gflags, которая поставляется вместе с инструментами отладки Windows. С его помощью вы можете сделать так, чтобы у каждого выделения кучи была своя собственная страница - это поможет отследить переполнение памяти и двойное освобождение сразу в момент возникновения проблемы.

Я написал инструкции в своем блоге:

http://www.atalasoft.com/cs/blogs/loufranco/archive/2007/02/06/6-_2200_Pointers_2200_-on-Debugging-Unmanaged-Code.aspx

Есть и другие советы, как найти такую ​​ошибку там.

0 голосов
/ 22 июля 2014

Я сомневаюсь, что это затронет многих людей, так как это довольно неясно, но если вы получите свой ФАЙЛ *, как это:

HANDLE hMyFile = CreateFile(...);
FILE* pFile = _fdopen( _open_osfhandle((long)hMyFile, <flags>), "rb" );
CloseHandle(hMyFile);

Тогда вы будете пропускать поток для каждого файла, который вы открываете. После выполнения _open_osfhandle и _fdopen вы должны вызвать fclose () для pFile, чтобы закрыть свой дескриптор. Очевидно, что CloseHandle недостаточно умен, чтобы освободить крошку, которую fdopen ассоциирует с вашей ручкой, но fclose достаточно умен, чтобы закрыть вашу ручку вместе с флайтом * связанным с фрейтом.

Приложение, над которым я работал, делало это, потому что определенный API передавался через HANDLE, а конкретному разработчику API требовался FILE *, поэтому разработчик делал _fdopen / _open_osfhandle для получения FILE *. Однако это означало, что вызова CloseHandle вызывающей стороны было недостаточно для полного закрытия HANDLE. Исправление должно было сначала дублировать входящую HANDLE, затем код FILE * мог правильно fclose () FILE *, не нарушая HANDLE вызывающего.

Пример сломанной программы:

#include "stdafx.h"
#include <Windows.h>
#include <io.h>
#include <assert.h>
#include <fcntl.h>
int _tmain(int argc, _TCHAR* argv[])
{

  for(int x = 0;x < 1024; x++)
  {
    HANDLE hFile = CreateFile(L"c:\\temp\\rawdata.txt",GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    FILE* pFile =  _fdopen( _open_osfhandle((long)hFile, _O_RDONLY | _O_BINARY), "rb" );
    assert(pFile); // this assert will go off at x=509, because _getstream() only has 512 streams, and 3 are reserved for stdin/stdout/stderr
    CloseHandle(hFile);
  }

    return 0;
}
0 голосов
/ 06 ноября 2008

Я подозреваю, что с этой частью вашей программы все в порядке. Наиболее вероятный сценарий состоит в том, что у вас в коде ранее было какое-то повреждение памяти, и это именно то, где он обнаруживается.

Вы пробовали запустить его через остальную часть программы (после этой части) в режиме отладки? Если является каким-либо повреждением памяти, распределитель режима отладки должен отловить его, когда он собирается освободить поврежденные области памяти, если не раньше. Предполагая, что вы используете компилятор с тщательным отладчиком памяти, конечно.

0 голосов
/ 06 ноября 2008

Я думаю, что что-то не так с fileName (у него есть конечный ноль?)

Попробуйте прокомментировать fopen и посмотрите, что произойдет.

...