web-dev-qa-db-fra.com

Erreur critique détectée c0000374 - La dll C++ renvoie le pointeur de la mémoire allouée à C #

J'ai une dll c ++ qui sert certaines fonctionnalités à mon application c # principale . Ici, j'essaie de lire un fichier, de le charger en mémoire, puis de retourner des informations telles que le pointeur sur les données chargées et le nombre de blocs de mémoire en c #. La Dll lit le fichier en mémoire avec succès, mais lors du retour à l'application principale, le programme se bloque en raison d'une corruption de tas (une erreur critique a été détectée c0000374).

Le code est assez simple et direct et j’ai déjà fait des choses similaires sans aucun problème. Cependant, je n’arrivais pas à comprendre ce qui faisait le problème ici, j’ai essayé d’allouer de la mémoire en utilisant "new, malloc et GlobalAlloc" mais n’a pas aidé. Les codes sont les suivants:

C++ MyDll:

typedef unsigned long         U32;

extern "C" __declspec(dllexport) int ReadFile(LPSTR Path, U32** DataPtr, U32* Count)
{
   FILE *fp;
   U32 *Data;
   CString tempStr(Path);
   long fSize;

   if(!(fp = fopen(tempStr, "rb"))) {
    return 0;
   }

   // Obtain File Size;
   fseek(fp, 0, SEEK_END);
   fSize =  ftell(fp);
   rewind(fp);

   Data = (U32 *)GlobalAlloc(0, fSize);
   if(Data == NULL) {
            fclose(fp);
            return -1;
    }

    // Copy file into the buffer.
        if(!(*Count = fread(Data, sizeof(U32), fSize / sizeof(U32), fp))) {
           fclose(fp);
           free(Data);
           return -2;
        }

   *DataPtr = (U32 *)Data;
       return 1;
}

Application C #:

        [DllImport(@"MyDll.dll", CallingConvention= CallingConvention.Cdecl)]
    private static extern int ReadFile([MarshalAs(UnmanagedType.LPStr)]string Path, out IntPtr dataPtr, out uint Count);

private void readDump(string Path)
{
    uint count = 0;
    IntPtr Data = new IntPtr();

   try{
       if(ReadFile(Path, out Data, out count) == 1) //The Program crashes just right after this statement
       {
           //Do Something ...
       }
    }
    catch() {}

}

Le programme se bloque en mode débogage et libération. À moins que je suspende le programme en mode débogage après avoir chargé le fichier et appelé des blocs de mémoire dans la "fenêtre immédiate de Visual Studio" . La taille des fichiers à charger est d'environ 64 Mo et nous disposons de plus de 2 Go de mémoire RAM inutilisée. PC.

UPDATE: J'ai remarqué que certains programmes tiers pour lesquels ils travaillaient auparavant plantaient avec "Code d'exception: c0000005" et que d'autres événements étranges se produisaient dans Windows 7 (l'hôte). J'ai donc testé le code dans une autre installation de Windows et tout semble fonctionner comme il se doit. Donc, probablement, il est lié à Windows 7. Maintenant, comment puis-je résoudre le problème? "sfc/scannow" n'a trouvé aucun problème.

6
2i3r

Si tout votre code correspond bien à ce qui est montré ci-dessus, je ne vois pas le problème. Cependant, lorsque ce problème survient, parfois parce que malloc/new/quoi que ce soit détecte une corruption de tas, cette corruption s’est déjà déjà produite dans le programme, mais le crash a été retardé jusqu’à l’appel suivant à new/malloc.

Si vous lisez d'autres fichiers, ou allouez ou libérez d'autres mémoires tampons avant que la procédure ci-dessus ne soit exécutée et tombe en panne, je rechercherais des problèmes. Peut-être lancer une série d’affirmations partout où vous écrivez dans les mémoires tampons et vérifiez les limites et ce que vous écrivez pour les dépassements ..__ Désolé, ce n’est pas une réponse concrète, je n’ai pas assez de rep pour laisser cet avis en commentaire.

20
Freya301

Vous allouez les données de sortie 2 fois . Une fois en C # en tant que nouveau IntPtr, puis en C++ en tant que GlobalAlloc, puis renvoyez le pointeur renvoyé par GlobalAlloc. Ainsi, le pointeur renvoyé par new intPtr a été perdu.

1
Kalpesh