2008-11-06 8 views
1

L'exception mentionnePourquoi `_getstream` échouerait-il?

FILE* __cdecl _getstream 

J'appelle fopen et il se bloque.

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

Pour une raison quelconque, je n'arrive jamais à la deuxième boîte de message. Fait intéressant, lorsque je suis en mode débogage, l'application fonctionne parfaitement. Pourquoi?

+0

Je presque soupçonner un problème de permissions liées. Exécuter en mode débogage signifie élevé? Quel système d'exploitation et quel environnement de développement? – cfeduke

+0

Qu'est-ce que "FILE * __cdecl _getstream" en haut de votre message? De plus, vous n'avez pas besoin de parenthèses autour du "rb". – paxdiablo

Répondre

-1

Je suppose que quelque chose ne va pas avec fileName (at-il de fuite zéro?)

Essayez de commenter fopen ligne et voir ce qui se passera.

0

Je suppose qu'il n'y a rien de mal avec cette partie de votre programme. Le scénario le plus probable est que vous avez une sorte de corruption de la mémoire plus tôt dans le code, et cela arrive juste à l'endroit où il apparaît.

Avez-vous essayé de l'exécuter dans le reste du programme (après cette partie) en mode débogage? Si est une sorte de corruption de la mémoire, l'allocateur de mode débogage devrait l'attraper quand il va libérer les zones corrompues de la mémoire, sinon plus tôt. En supposant que vous utilisez un compilateur avec un allocateur de mémoire de débogage complet, bien sûr.

+0

Le problème est que le problème ne se produit pas en mode débogage. Et cela arrive aussi seulement pour certains fichiers, pas tous. Je pense que vous avez raison. Je suppose que je vais aller voir l'allocation de mémoire pour l'ensemble du processus. Pas facile en mode release. – baash05

2

Je pense que la corruption de la mémoire. Sur Windows (que le __cdecl me fait penser utiliser), il y a l'utilitaire gflags fourni avec les outils de débogage de Windows. Avec lui, vous pouvez faire en sorte que chaque allocation de tas ait sa propre page - cela aidera à rattraper les dépassements de mémoire et à libérer deux fois immédiatement au moment du problème.

j'ai écrit des instructions sur mon blog:

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

Il y a d'autres conseils pour trouver ce genre de bug là aussi.

0

Je doute que cela affectera beaucoup de gens car cela est assez obscur, mais si vous obtenez votre fichier * comme ceci:

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

Ensuite, vous fuite d'un jet pour chaque fichier que vous ouvrez. Après avoir fait _open_osfhandle et _fdopen, vous devez appeler fclose() sur le fichier pFile pour fermer votre handle. CloseHandle n'est apparemment pas assez intelligent pour libérer le croc que fdopen associe à votre poignée, mais fclose est assez intelligent pour fermer votre poignée avec le croc de FILE *. L'application sur laquelle je travaillais faisait cela parce qu'une certaine API passait autour des HANDLEs, et un implémenteur particulier de l'API avait besoin d'un FICHIER *, donc l'implémenteur a fait le truc _fdopen/_open_osfhandle pour obtenir un FICHIER *. Cependant, cela signifiait que l'appel CloseHandle de l'appelant était insuffisant pour fermer complètement le HANDLE. Le correctif consistait à dupliquer d'abord le HANDLE entrant, puis le code FILE * pouvait correctement fclose() le FICHIER * sans casser le HANDLE de l'appelant.

programme cassé Exemple:

#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; 
}