Esecuzione di un 'GC.Collect' corregge il mio incidente, ma io non capisco perché

StackOverflow https://stackoverflow.com/questions/995294

  •  13-09-2019
  •  | 
  •  

Domanda

Ho questo pezzo di codice (dalla connettività PC Nokia Codice 3.2 esempio, in C #):

  DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo =
  new DAContentAccessDefinitions.CA_FOLDER_INFO();
  folderInfo.iSize = Marshal.SizeOf(folderInfo); //(32)

  IntPtr bufItem = Marshal.AllocHGlobal(folderInfo.iSize);

  //I often get a AccessViolationException on the following line
  Marshal.StructureToPtr(folderInfo, bufItem, true);

Se corro GC.Collect() all'inizio di questo, allora non ottengo un AccessViolationException. Ma io non voglio rallentare questa funzione solo se necessario. Ho provato a mettere GC.Keepalive in vari luoghi, ma senza successo.

CA_FOLDER_INFO è definito come:

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
    public struct CA_FOLDER_INFO
    {
        public int iSize;
        public int iFolderId;
        public int iOptions;
        public string pstrName;
        public string pstrPath;
        public int iSubFolderCount;
        public IntPtr pSubFolders;
        public IntPtr pParent;
    }

Non, in questo caso, richiedono una delle due corde, e cambiando le loro definizioni di IntPtr sembra rendere l'eccezione andare via.

Che cosa sta succedendo qui, e qual è il modo corretto per evitare che l'eccezione?

È stato utile?

Soluzione

Il problema è che si sta passando fedele alla Marshal.StructureToPtr così tenta di liberare i due puntatori di stringa (che a volte sono validi). È necessario passare falso in questo caso dal momento che hai appena assegnato che la memoria sul mucchio. (Vale a dire non c'è niente per liberare lì).

Altri suggerimenti

Sei sicuro Marshal.SizeOf (bufItem) e Marshal.SizeOf (FolderInfo) sono la stessa cosa?

E, forse il fatto che non si inizializza le corde? Dal momento che tu dici non si ottiene l'errore quando sono IntPtr (che per default è IntPtr.Zero), mi piacerebbe provare entrambi impostazione stringhe vuote, prima di provare a marshalling la voce di buffer.

[Edit]

Forse si dovrebbe provare appuntare la maniglia del buffer, e marshalling che alla struttura, piuttosto che nei versa. Qualcosa di simile a questo:

DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo;

GCHandle pinnedHandle = GCHandle.Alloc(buffItem, GCHandleType.Pinned);
folderInfo = (DAContentAccessDefinitions.CA_FOLDER_INFO)Marshal.PtrToStructure(pin.AddrOfPinnedObject(), typeof(DAContentAccessDefinitions.CA_FOLDER_INFO));
pin.Free();

//folderInfo should contain the data from buffItem

Usa la parola chiave fissa per ottenere un puntatore al folderInfo originale.

E 'possibile che le risorse non gestite non vengono rilasciate da qualcosa. Controllare per vedere se qualcosa si sta utilizzando attrezzi IDisposable in caso affermativo, avvolgerlo in un blocco using { }.

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