Preciso excluir estruturas arregimentados via Marshal.PtrToStructure em código não gerenciado?

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

  •  20-08-2019
  •  | 
  •  

Pergunta

Eu tenho esse código C ++:

extern "C" __declspec(dllexport) VOID AllocateFoo(MY_DATA_STRUCTURE** foo)
{
    *foo = new MY_DATA_STRUCTURE;

    //do stuff to foo
}

Então, em C # eu chamar a função assim:

[DllImport("MyDll.dll")]
static extern void AllocateFoo(out IntPtr pMyDataStruct);

...

MyDataStructure GetMyDataStructure()
{
    IntPtr pData;
    ManagedAllocateFooDelegate(out pData);

    MyDataStructure foo = (MyDataStructure)Marshal.PtrToStructure(pData, typeof(MyDataStructure));
    return foo;
}

Onde MyDataStructure é um struct (não de classe) que corresponde a MY_DATA_STRUCTURE e os membros são empacotadas de forma adequada.

Assim perguntas: eu preciso para armazenar pData e depois liberá-lo novamente em código não gerenciado quando MyDataStructure é GC'd? MSDN diz para Marshal.PtrToStructure (IntPtr, Type): "Marechais de dados de um bloco não gerenciado de memória para um objeto gerenciado recém-alocado do tipo especificado." Em que a sentença faz "Marshall" média "cópia"? Caso em que eu precisaria para preservar (IntPtr pData) e, em seguida, passá-lo para código não gerenciado (no destruidor MyDataStructure) para que eu possa fazer um C ++ "delete"?

Eu procurei, mas não consigo encontrar uma resposta suficientemente explícita para isso.

Foi útil?

Solução

Como Erik disse, o Marechal não cópia média, mas eu não acho que ele respondeu o principal ponto de sua pergunta.

Você precisa segurar o ponteiro nativo pData até o MyDataStructure é GCed? Não.

Uma vez empacotado, sua instância MyDataStructure, foo, contém uma cópia da estrutura apontada por pData. Você não precisa agarrar pData por mais tempo. Para evitar um vazamento de memória, você deve passar que pData em outra função não gerenciada que irá excluí-lo, e que pode ser feito logo após o empacotamento, independentemente de quanto tempo você segurar a instância MyDataStructure.

Outras dicas

Sim, neste caso, copie meios Marshall; Assim, você precisa desalocar a memória em código não gerenciado. Toda a chamada para PtrToStructure faz é ler um número de bytes indicado pelo tamanho da estrutura de destino 'MyDataStructure' a partir da localização de memória apontada por pData.

Os detalhes do curso depender exatamente o que 'MyDataStructure' olha como (fazer você usar qualquer FieldOffset ou StructLayout atributos em MyDataStructure) -. Mas o resultado final é que o retorno do PtrToStructure é uma cópia dos dados

Como GBegen aponta em sua resposta , eu não respondi o principal ponto de sua pergunta. Sim, você terá de apagar a cópia não gerenciado de sua estrutura em código não gerenciado, mas não, você não precisa se agarrar pData - você pode excluir a cópia não gerenciado, assim que a chamada para concluído PtrToStructure

.

PS:. Eu editei o meu post para conter esta informação, de modo a consolidar as respostas em um pós - se alguém upvotes esta resposta, por favor upvote resposta de GBegen, bem como para a sua contribuição

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