2012-07-09 10 views
8

Muszę przekazać zarządzane wywołanie zwrotne do niezarządzanego odbiornika TCP. Ponieważ jest to wątek, który musi istnieć przez cały czas trwania aplikacji, muszę uniemożliwić gromadzenie śmieci. Przeczytałem wszędzie, że wskaźniki funkcji przypinania nie są wymagane, a GCHandle.Alloc wykona zadanie zapobiegania zbieraniu śmieci.Przypnij wskaźnik funkcji

Ale czy to jest dane? Widziałem, że AppPool obsługujący ten kod ulega awarii z naruszeniem dostępu. Dlaczego nie powinienem podejrzewać, że ten błąd występuje, ponieważ wskaźnik funkcji został zebrany śmieci?

Ta post obsługuje ten fakt.

Aktualizacja: Wydaje się, że znacznie zmniejszyło to liczbę wypadków. Czy jest jakiś problem z tym podejściem?

typedef void (__cdecl *ProcMessageFunc)(void* param, void* paramBuf, ULONG bufSize); 
FuncDelegate^ fp = gcnew MessageFuncDelegate(this, &Handler); 
pin_ptr<MessageFuncDelegate^> pinnedFunctionPointer = &fp; 
ret = Receiver ((ProcMessageFunc)pinnedFunctionPointer); 
+3

Przechowywanie obiektu uczestnika w zmiennej statycznej jest wystarczające. Kod macierzysty może bombardować naruszeniami dostępu z wielu innych powodów. –

+0

Zrobiłem dokładnie to. Powodem, dla którego mam skłonność do podejrzeń, że wywóz śmieci jest taki, jest to, że naruszenie zasad dostępu występuje nieprawidłowo. Co ważniejsze, stos wywołań w zrzucie awaryjnym widzę natywną bibliotekę dll, po której następuje clr.dll, a następnie kernel32.dll na szczycie stosu. Ta kolejność jest spójna. – Krishter

Odpowiedz

8

zrobić dokładnie to, co proponuję zrobić - GCHandle.Alloc na delegata ale bez pinningu - i nie miał żadnych problemów w szerokie zastosowanie na wielu różnych platformach i na wersji .NET 2.0 - 4. Coś jak:

DelegateHandle = GCHandle.Alloc(xlDelegate); 
FunctionPointer = Marshal.GetFunctionPointerForDelegate(xlDelegate); 

z FunctionPointer następnie przekazywane do natywnego kodu i DelegateHandle przechowywane do późniejszego czyszczenia.

Wydaje się, że jest to najlepszy numer referencyjny: http://msdn.microsoft.com/en-us/library/367eeye0(v=vs.80).aspx.

Nic w poście, o którym mówisz, jest sprzeczne z tym odniesieniem - musisz zabezpieczyć delegata przed zbieraniem śmieci, po prostu nie jest wymagane przypinanie .

+0

Czy przypinanie adresów dla funkcji nie jest konieczne, ponieważ w przeciwieństwie do obiektów sterty istnieją one w lokalizacji stałej? Jaki adres ma funkcja, jeśli nie została jeszcze JIT? – Dai

+2

Wydaje mi się, że wywołanie funkcji GetFunctionPointerForDelegate tworzy niewielki element pośredniczący, który ma ustalony punkt wejścia, ale jeśli delegat zostanie przeniesiony, kod pośredniczący nadal będzie wiedział, jak go wywołać. Zatem wyeksportowany wskaźnik funkcji nie jest bezpośrednim eksportem adresu obiektu delegata (w przeciwieństwie do przypiętej tablicy lub elementu struct byłby). Pamiętaj, że wyeksportowana "natywna" funkcja musi również implementować rodzime -> zarządzane przejście. – Govert

+0

To jest dokładnie to, co zrobiłem. Niestety nadal występuje naruszenie dostępu. Pozwól, że powiem to w ten sposób. Jak mogę być całkowicie pewien, że NIE jest to przyczyną naruszenia zasad dostępu? – Krishter