Libération de la mémoire non gérée à partir de C# avec le pointeur de

La question en quelques mots :
Comment libérer de la mémoire retourné à partir de DLL Native comme ItrPtr en code managé?

Détails :
Considérons le cas simple de la fonction prend deux paramètres en SORTIE, Le premier est un Pointeur de Référence pour le tableau d'octets et le second est la Référence Int .
La fonction permet d'allouer de la quantité d'octets selon certaines règles et de retourner le pointeur de la mémoire et de la taille d'octets et de la valeur de retour (1 succès et 0 pour non) .

Le code ci-dessous fonctionne très bien et je peux obtenir le tableau d'octets correctement et le nombre d'octets et la valeur de retour, mais quand j'ai essayer de libérer de la mémoire à l'aide du pointeur (IntPtr) - je obtenir de l'exception :

Windows a déclenché un point d'arrêt dans TestCppDllCall.exe.

Cela peut être dû à une corruption du tas, ce qui indique un bug dans TestCppDllCall.exe ou une Dll qu'il a chargé.

Cela peut être dû également à l'utilisateur en appuyant sur F12 pendant TestCppDllCall.exe a le focus.

La fenêtre de sortie peut avoir plus d'informations de diagnostic.

À mettre les choses au clair :

  1. Le prochain code C# fonctionner correctement avec d'autres DLL fonction ont la même signature et de libérer la mémoire fonctionne sans aucun problème .
  2. Toute modification à l'alinéa C) du code accepté si vous avez besoin de modifier l'allocation de la mémoire de la méthode ou de l'ajout de tout autre code .
  3. Toutes les fonctionnalités dont j'ai besoin est originaire DLL fonction accepte Deux paramètres par référence (tableau d'Octets et de type int En c# [IntPtr de tableau d'octets et int]) remplir avec certaines valeurs en fonction de certaines règles et de retourner le résultat (Succès ou Échec) .

CppDll.h

#ifdef CPPDLL_EXPORTS
#define CPPDLL_API __declspec(dllexport)
#else
#define CPPDLL_API __declspec(dllimport)
#endif

extern "C" CPPDLL_API int writeToBuffer(unsigned char *&myBuffer, int& mySize);

CppDll.cpp

#include "stdafx.h"
#include "CppDll.h"

extern "C" CPPDLL_API int writeToBuffer(unsigned char*& myBuffer, int& mySize)
{
    mySize = 26;

    unsigned char* pTemp = new unsigned char[26];
    for(int i = 0; i < 26; i++)
    {
        pTemp[i] = 65 + i;
    }
    myBuffer = pTemp; 
    return 1;
}

De code C#:

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace TestCppDllCall
{
    class Program
    {
        const string KERNEL32 = @"kernel32.dll";
        const string _dllLocation = @"D:\CppDll\Bin\CppDll.dll";
        const string funEntryPoint = @"writeToBuffer";

        [DllImport(KERNEL32, SetLastError = true)]
        public static extern IntPtr GetProcessHeap();
        [DllImport(KERNEL32, SetLastError = true)]
        public static extern bool HeapFree(IntPtr hHeap, uint dwFlags, IntPtr lpMem);
        [DllImport(_dllLocation, EntryPoint = funEntryPoint, CallingConvention = CallingConvention.Cdecl)]
        public static extern int writeToBuffer(out IntPtr myBuffer, out int mySize);

        static void Main(string[] args)
        {
            IntPtr byteArrayPointer = IntPtr.Zero;
            int arraySize;
            try
            {
                int retValue = writeToBuffer(out byteArrayPointer, out arraySize);
                if (retValue == 1 && byteArrayPointer != IntPtr.Zero)
                {
                    byte[] byteArrayBuffer = new byte[arraySize];
                    Marshal.Copy(byteArrayPointer, byteArrayBuffer, 0, byteArrayBuffer.Length);
                    string strMyBuffer = Encoding.Default.GetString(byteArrayBuffer);
                    Console.WriteLine("Return Value : {0}\r\nArray Size : {1}\r\nReturn String : {2}",
                        retValue, arraySize, strMyBuffer);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Error calling DLL \r\n {0}", ex.Message);
            }
            finally
            {
                if (byteArrayPointer != IntPtr.Zero)
                    HeapFree(GetProcessHeap(), 0, byteArrayPointer);
            }
            Console.ReadKey();
        }
    }
}

Quand je debug ce code que j'ai mis un point de rupture dans la ligne (retour 1) et la valeur de la solution tampon a été :

myBuffer = 0x031b4fc0 "ABCDEFGHIJKLMNOPQRSTUVWXYZ‎‎‎‎««««««««î‏"

Et j'ai eu la même valeur dans le code C# lorsque la fonction de retour d'appel et de la valeur de a :

52121536

Le résultat que j'ai Obtenu le bon pointeur de la Mémoire et je suis en mesure d'obtenir le tableau d'octets de la valeur , de la façon de libérer de ces blocs de mémoire avec ce pointeur en C# ?

S'il vous plaît laissez-moi savoir si quelque chose n'est pas clair ou s'il y a un faute de frappe, je ne suis pas de langue maternelle anglaise .

OriginalL'auteur khaled | 2012-09-05