Exécution d'un « GC.Collect » corrige mon accident, mais je ne comprends pas pourquoi

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

  •  13-09-2019
  •  | 
  •  

Question

J'ai ce morceau de code (de la connectivité Nokia PC Code 3.2 exemple, 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 je cours GC.Collect() au début de cela, alors je ne suis pas un AccessViolationException. Mais je ne veux pas ralentir cette fonction que si nécessaire. Je l'ai essayé de mettre GC.Keepalive en divers endroits, mais sans succès.

CA_FOLDER_INFO est défini comme suit:

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

Je ne suis pas, dans ce cas, nécessitent soit des cordes, et en changeant leurs définitions IntPtr semble faire l'exception disparaître.

Qu'est-ce qui se passe ici, et quelle est la bonne façon de prévenir l'exception?

Était-ce utile?

La solution

Votre problème est que vous passez vrai Marshal.StructureToPtr il tente de libérer les deux pointeurs de chaîne (qui sont parfois invalides). Vous devez passer de faux dans ce cas, puisque vous vient d'allouer cette mémoire sur le tas. (À savoir qu'il n'y a rien pour y libérer).

Autres conseils

Êtes-vous sûr Marshal.Sizeof (bufItem) et Marshal.Sizeof (FolderInfo) sont les mêmes?

Et, peut-être le fait que vous n'êtes pas initialisez les chaînes? Puisque vous dites que vous ne recevez pas l'erreur quand ils sont IntPtr (qui par défaut IntPtr.Zero), je vais essayer de les mettre à la fois à des chaînes vides avant d'essayer marshaling l'élément tampon.

[Modifier]

Peut-être que vous devriez essayer épingler la poignée de tampon et marshaling que la structure, plutôt que vis versa. Quelque chose comme ceci:

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

Utilisez le mot-clé fixe pour obtenir un pointeur sur votre folderInfo d'origine.

Il se pourrait que les ressources non gérés ne sont pas libérés par quelque chose. Vérifiez si tout ce que vous utilisez des outils IDisposable le cas échéant, l'envelopper dans un bloc de using { }.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top