Domanda

Continuo a ricevere un AccessViolationException quando si chiama il seguente da una DLL esterna:

FILES_GetMemoryMapping(MapFile, out size, MapName, out PacketSize, pMapping, out PagePerSector);

Che ha un prototipo che ho l'installazione in quanto tale:

    [DllImport("Files.DLL", SetLastError = true)]
    public static extern uint FILES_GetMemoryMapping(
        [MarshalAs(UnmanagedType.LPStr)]
        string pPathFile,
        out ushort Size,
        [MarshalAs(UnmanagedType.LPStr)]
        string MapName,
        out ushort PacketSize,
        IntPtr pMapping,
        out byte PagesPerSector);

Ora, l'argomento che sta causando questo è più probabile il 5 ° uno (IntPtr pMapping). Ho porting questo codice sopra da un'applicazione C ++ in C #. La 5 argomentazione è un puntatore a una struttura che contiene anche un puntatore ad un'altra struct. Qui di seguito è come ho questi configurazione sctructs:

    [StructLayout(LayoutKind.Sequential)]
    public struct MappingSector
    {
        [MarshalAs(UnmanagedType.LPStr)]
        public string Name;
        public uint dwStartAddress;
        public uint dwAliasedAddress;
        public uint dwSectorIndex;
        public uint dwSectorSize;
        public byte bSectorType;
        public bool UseForOperation;
        public bool UseForErase;
        public bool UseForUpload;
        public bool UseForWriteProtect;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct Mapping
    {
        public byte nAlternate;
        [MarshalAs(UnmanagedType.LPStr, SizeConst=260)]
        public string Name;
        public uint NbSectors;
        public IntPtr pSectors;
    }

L'equivalente C ++ di questi sono i seguenti:

typedef struct {
    char*       Name;
    DWORD       dwStartAddress;
    DWORD       dwAliasedAddress;
    DWORD       dwSectorIndex;
    DWORD       dwSectorSize;
    BYTE        bSectorType;
    BOOL        UseForOperation;
    BOOL        UseForErase;
    BOOL        UseForUpload;
    BOOL        UseForWriteProtect;
} MAPPINGSECTOR, *PMAPPINGSECTOR;

typedef struct {
    BYTE            nAlternate;
    char            Name[MAX_PATH]; // MAX_PATH = 260
    DWORD           NbSectors;
    PMAPPINGSECTOR  pSectors;   
} MAPPING, *PMAPPING;

Ho la sensazione che ho fatto qualcosa di sbagliato o con il porting su questi le strutture, o porting sopra il prototipo di funzione. Una questione Marshalling di somesort.

La funzione di tutta la strada nella parte superiore di questo post viene chiamato due volte nel mio codice. Una volta con pMapping impostato nullo (questo mette un valore di "size"). Memoria viene allocata una nuova struct utilizza questo parametro di dimensione e la funzione viene richiamata nuovamente ora con un puntatore a questo spazio di memoria allocata per pMapping. (PMapping ha anche un puntatore per l'altro struct che ottiene anche qualche spazio assegnato durante questo periodo).

Ecco il vecchio codice C ++ che compie questo:

FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)MapName, &PacketSize, pMapping, &PagePerSector);
// Allocate the mapping structure memory
pMapping = (PMAPPING)malloc(sizeof(MAPPING));
pMapping->NbSectors = 0;
pMapping->pSectors = (PMAPPINGSECTOR) malloc((Size) * sizeof(MAPPINGSECTOR));
printf("mapsectorsize: <%d>\n", football);
printf("pMappingsize: <%d>\n", f2);  
// Get the mapping info
FILES_GetMemoryMapping((LPSTR)(LPCTSTR)MapFile, &Size, (LPSTR)(LPCTSTR)MapName, &PacketSize, pMapping, &PagePerSector);

Inizialmente ho pensato che non era ripartisce la corretta quantità di spazio così ho provato il vecchio codice C ++ sopra e scoperto che:

sizeof(MAPPING) = 272
and
sizeof(PMAPPINGSECTOR) = 40

Ho fatto lo stesso controllo nel mio codice C # e trovato il seguente:

Marshal.SizeOf(new Mapping()) = 16
and
Marshal.SizeOF(new MappingSector()) = 40

Abbiamo un problema qui. La struct mappatura dovrebbe essere di dimensioni 272, ma il suo solo 16. Pensando ho potuto solo fare una soluzione rapida, ho assegnato manualmente 272 invece di 16 qui, ma ancora con errori fuori con un AccessViolationException.

Qualche idea su come risolvere questo problema? O che cosa potrebbe ancora andare male?

È stato utile?

Soluzione

'prototipo' non era la parola corretta, mi piace "dichiarazione DllImport" meglio.

E ho appena capito di lavoro.

così in C ++:

typedef struct {
    BYTE                        nAlternate;
    char                        Name[MAX_PATH]; // MAX_PATH = 260
    DWORD                       NbSectors;
    PMAPPINGSECTOR      pSectors;       
} 

per C #:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public struct Mapping
{
    public byte nAlternate;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=260)]
    public char[] Name;
    public uint NbSectors;
    public IntPtr pSectors;
}

un array di caratteri non è una stringa, e deve essere trattato come un array di caratteri .... Chi avrebbe mai detto: P

Altri suggerimenti

Secondo MSDN , si dovrebbe passare uno StringBuilder per un buffer lunghezza fissa. Provare quanto segue, o qualche variante (non testata):

[StructLayout(LayoutKind.Sequential)]
public struct Mapping
{
    public byte nAlternate;
    [MarshalAs(UnmanagedType.LPStr, SizeConst=260)]
    public StringBuilder Name;
    public uint NbSectors;
    public IntPtr pSectors;

    public Mapping()
    {
        Name = new StringBuilder(259); 
        //This will be a buffer of size 260 (259 chars + '\0')
    }
}

Non ho lavorato tutto questo, ho paura, ma se hai le strutture con 'char *' s in e stai li smistamento come 'stringa', allora si dovrebbe fare attenzione ad essere decorare roba con il charset = appropriata attributi CharSet.Ansi.

Una cosa che sarebbe utile aggiungere al vostro invio è il prototipo C ++ per la funzione (non mi riferisco alla tua dichiarazione DllImport come un 'prototipo', ma che potrebbe essere solo me.)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top