El funcionamiento de un 'GC.Collect' corrige mi accidente, pero no entiendo por qué

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

  •  13-09-2019
  •  | 
  •  

Pregunta

Tengo este pedazo de código (de la conectividad de Nokia PC Código 3.2 ejemplo, en 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);

Si me quedo GC.Collect() al comienzo de esta, entonces no consigo un AccessViolationException. Pero no quiero para frenar esta función si no es necesario. He intentado poner GC.Keepalive en varios lugares, pero sin éxito.

CA_FOLDER_INFO se define como:

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

No, en este caso, obligan a las cuerdas, y el cambio de sus definiciones a IntPtr parece hacer la excepción desaparece.

Lo que está pasando aquí, y lo que es la forma correcta para evitar la excepción?

¿Fue útil?

Solución

Su problema es que estás pasando fiel a Marshal.StructureToPtr por lo que los intentos para liberar a los dos punteros de cadena (que a veces no son válidos). Tiene que pasar falsa en este caso ya que sólo se asigna esa memoria en el montón. (Es decir, no hay nada para liberar allí).

Otros consejos

¿Está seguro Marshal.Sizeof (bufItem) y Marshal.Sizeof (FolderInfo) son los mismos?

Y, tal vez el hecho de que no se está inicializando los hilos? Puesto que usted dice que no recibe el error cuando están IntPtr (que por defecto es IntPtr.Zero), que iba a tratar el establecimiento de los dos para cadenas vacías antes de intentar el cálculo de referencias del elemento de amortiguación.

[Editar]

Tal vez usted debe tratar de fijar el mango de amortiguamiento, y el cálculo de referencias que a la estructura, en lugar de en relación inversa. Algo como esto:

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

Usar la palabra clave fija para obtener un puntero a su folderInfo originales.

Podría ser que los recursos no administrados no están siendo liberados por algo. Comprobar para ver si hay algo que está utilizando implementos IDisposable y si es así, lo envuelve en un bloque using { }.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top