Pergunta

Eu tenho este pedaço de código (a partir da conectividade 3.2 exemplo de código Nokia PC, em 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 eu executar GC.Collect() no início deste, então eu não obter uma AccessViolationException. Mas eu não quero abrandar esta função a menos que necessário. Eu tentei colocar GC.Keepalive em vários lugares, mas sem sucesso.

CA_FOLDER_INFO é definido 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;
    }

Não, neste caso, exigir quer das cordas, e alterando suas definições para IntPtr parece fazer a exceção ir embora.

O que está acontecendo aqui, e qual é a maneira correta para evitar a exceção?

Foi útil?

Solução

Seu problema é que você está passando fiel a Marshal.StructureToPtr por isso tenta libertar os dois ponteiros de cordas (que às vezes são inválidos). Você precisa passar falsa, neste caso, já que você só alocados que a memória no heap. (Ou seja, não há nada para libertar lá).

Outras dicas

Você tem certeza Marshal.SizeOf (bufItem) e Marshal.SizeOf (FolderInfo) são os mesmos?

E, talvez o fato de que você não está inicializando as cordas? Desde que você diz que você não obter o erro quando estão IntPtr (cujo padrão é IntPtr.Zero), eu tentaria colocá-los tanto para esvaziar cordas antes de tentar empacotamento o item buffer.

[Edit]

Talvez você deve tentar fixar a alça de buffer, e empacotamento que a estrutura, em vez de vis versa. Algo parecido com isto:

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

Use a palavra-chave fixa para obter um ponteiro para o seu folderInfo originais.

Pode ser que recursos não gerenciados não estão sendo liberados por alguma coisa. Verifique para ver se alguma coisa que você está usando implementos IDisposable e em caso afirmativo, envolvê-la em um bloco using { }.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top