2012-11-29 11 views
24

2012-12-09 सारांश:विनाश

  • एक सामान्य मिश्रित मोड आवेदन वैश्विक देशी सी ++ finalizers के रूप में चलाने विनाशकर्ता में। उस व्यवहार या संबंधित टाइमआउट को बदलना संभव नहीं है।
  • एक मिश्रित-मोड असेंबली डीएलएल डीएलएल लोड/अनलोड के दौरान सी ++ कन्स्ट्रक्टर/विनाशकों को चलाता है - बिल्कुल मूल डीएलएल के रूप में।
  • COM12 इंटरफ़ेस का उपयोग कर देशी निष्पादन योग्य में सीएलआर को होस्ट करना deconstructors दोनों को देशी डीएलएल (व्यवहार की इच्छा है) में व्यवहार करने और अंतिमकर्ताओं (एक अतिरिक्त बोनस) के लिए टाइमआउट सेट करने की अनुमति देता है।
  • जहां तक ​​मेरा बता सकते हैं से कम से कम विजुअल स्टूडियो 2008, 2010 और 2012 (केवल .NET 4 के साथ परीक्षण)

वास्तविक CLR होस्टिंग निष्पादन मैं उपयोग करने की योजना बहुत के समान है पर लागू होता है कुछ मामूली परिवर्तन के अलावा इस सवाल में उल्लिखित एक:

  • कुछ मूल्य को OPR_FinalizerRun रूपरेखा (60 सेकंड वर्तमान में है, लेकिन विषय बदलने के लिए) के रूप में हंस Passant ने सुझाव दिया।
  • एटीएल कॉम स्मार्ट पॉइंटर वर्गों का उपयोग करना (ये विजुअल स्टूडियो के एक्सप्रेस संस्करणों में उपलब्ध नहीं हैं, इसलिए मैंने उन्हें इस पोस्ट से छोड़ा)।
  • CLRCreateInstancemscoree.dll गतिशील रूप से (कोई संगत सीएलआर स्थापित होने पर बेहतर त्रुटि संदेशों को अनुमति देने के लिए)।
  • मेजबान से कमांड लाइन को असेंबली डीएलएल में नामित Main फ़ंक्शन पर पास करना।

उन सभी के लिए धन्यवाद जिन्होंने प्रश्न और/या टिप्पणी पढ़ने के लिए समय निकाला।


2012-12-02 पोस्ट के नीचे अपडेट करें।

मैं विजुअल स्टूडियो 2012 का उपयोग .NET 4 के साथ मिश्रित मोड सी ++/सीएलआई एप्लिकेशन पर काम कर रहा हूं और यह पता चला है कि कुछ मूल वैश्विक वस्तुओं के विनाशकों को बुलाया नहीं जा रहा था। इस मुद्दे की जांच करना यह पता चला है कि वे प्रबंधित वस्तुओं की तरह व्यवहार करते हैं जैसा कि this post में बताया गया है।

मैं इस व्यवहार से काफी आश्चर्यचकित था (मैं इसे प्रबंधित वस्तुओं के लिए समझता हूं) और इसे कहीं भी दस्तावेज नहीं मिला, न तो C++/CLI standard और न ही destructors and finalizers के विवरण में।

Hans Passant द्वारा टिप्पणी में दिए गए सुझाव के बाद, मैंने कार्यक्रमों को एक असेंबली डीएलएल के रूप में संकलित किया और इसे एक छोटे से मूल निष्पादन योग्य में होस्ट किया और यह मुझे वांछित व्यवहार देता है (विनाशकों को एक ही धागे में खत्म करने और चलाने के लिए पर्याप्त समय दिया जाता है जैसा कि उनका निर्माण किया गया था)!

मेरे सवालों का:

  1. मैं एक अकेले खड़े निष्पादन में समान व्यवहार प्राप्त कर सकते हैं?
  2. यदि (1) संभव नहीं है तो निष्पादन योग्य के लिए प्रक्रिया समय समाप्ति नीति (यानी मूल रूप से ICLRPolicyManager->SetTimeout(OPR_ProcessExit, INFINITE) पर कॉल करना) को कॉन्फ़िगर करना संभव है?यह एक स्वीकार्य कामकाज होगा।
  3. यह दस्तावेज कहां है/मैं इस विषय पर खुद को और कैसे शिक्षित कर सकता हूं? मैं उस व्यवहार पर भरोसा नहीं करता जो बदलने के लिए उत्तरदायी है।

संकलन नीचे फ़ाइलों के रूप में निम्नानुसार पुन: पेश करने के लिए:

cl /EHa /MDd CLRHost.cpp 
cl /EHa /MDd /c Native.cpp 
cl /EHa /MDd /c /clr CLR.cpp 
link /out:CLR.exe Native.obj CLR.obj 
link /out:CLR.dll /DLL Native.obj CLR.obj 

अवांछित व्यवहार:

C:\Temp\clrhost>clr.exe 
[1210] Global::Global() 
[d10] Global::~Global() 

C:\Temp\clrhost> 

चल रहा है की मेजबानी:

C:\Temp\clrhost>CLRHost.exe clr.dll 
[1298] Global::Global() 
2a returned. 
[1298] Global::~Global() 
[1298] Global::~Global() - Done! 

C:\Temp\clrhost> 

प्रयुक्त फाइलें:

// CLR.cpp 
public ref class T { 
    static int M(System::String^ arg) { return 42; } 
}; 
int main() {} 

// Native.cpp 
#include <windows.h> 
#include <iostream> 
#include <iomanip> 
using namespace std; 
struct Global { 
    Global() { 
     wcout << L"[" << hex << GetCurrentThreadId() << L"] Global::Global()" << endl; 
    } 
    ~Global() { 
     wcout << L"[" << hex << GetCurrentThreadId() << L"] Global::~Global()" << endl; 
     Sleep(3000); 
     wcout << L"[" << hex << GetCurrentThreadId() << L"] Global::~Global() - Done!" << endl; 
    } 
} g; 

// CLRHost.cpp 
#include <windows.h> 
#include <metahost.h> 
#pragma comment(lib, "mscoree.lib") 

#include <iostream> 
#include <iomanip> 
using namespace std; 

int wmain(int argc, const wchar_t* argv[]) 
{ 
    HRESULT hr = S_OK; 
    ICLRMetaHost* pMetaHost = 0; 
    ICLRRuntimeInfo* pRuntimeInfo = 0; 
    ICLRRuntimeHost* pRuntimeHost = 0; 
    wchar_t version[MAX_PATH]; 
    DWORD versionSize = _countof(version); 

    if (argc < 2) { 
     wcout << L"Usage: " << argv[0] << L" <assembly.dll>" << endl; 
     return 0; 
    } 

    if (FAILED(hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS(&pMetaHost)))) { 
     goto out; 
    } 

    if (FAILED(hr = pMetaHost->GetVersionFromFile(argv[1], version, &versionSize))) { 
     goto out; 
    } 

    if (FAILED(hr = pMetaHost->GetRuntime(version, IID_PPV_ARGS(&pRuntimeInfo)))) { 
     goto out; 
    } 

    if (FAILED(hr = pRuntimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&pRuntimeHost)))) { 
     goto out; 
    } 

    if (FAILED(hr = pRuntimeHost->Start())) { 
     goto out; 
    } 

    DWORD dwRetVal = E_NOTIMPL; 
    if (FAILED(hr = pRuntimeHost->ExecuteInDefaultAppDomain(argv[1], L"T", L"M", L"", &dwRetVal))) { 
     wcerr << hex << hr << endl; 
     goto out; 
    } 

    wcout << dwRetVal << " returned." << endl; 

    if (FAILED(hr = pRuntimeHost->Stop())) { 
     goto out; 
    } 

out: 
    if (pRuntimeHost) pRuntimeHost->Release(); 
    if (pRuntimeInfo) pRuntimeInfo->Release(); 
    if (pMetaHost) pMetaHost->Release(); 

    return hr; 
} 

2012-12-02:
जहां तक ​​मेरा व्यवहार बता सकते हैं इस प्रकार हो रहा है:

  • एक मिश्रित-मोड EXE फ़ाइल में, वैश्विक विनाशकर्ता दौरान finalizers के रूप में चलाए जा रहे हैं डोमेनUnload चाहे वे मूल कोड या सीएलआर कोड पर रखा गया हो। विजुअल स्टूडियो 2008, 2010 और 2012 में यह मामला है।
  • प्रबंधित मूल पद्धति के चलते DLL_PROCESS_DETACH के दौरान वैश्विक मूल वस्तुओं के लिए मूल अनुप्रयोग विनाशकों द्वारा होस्ट किए गए मिश्रित मोड डीएलएल में चलाया जाता है और अन्य सभी सफाई हुई है। वे कन्स्ट्रक्टर के समान धागे में भागते हैं और उनके साथ जुड़े समय (वांछित व्यवहार) नहीं होता है। जैसा कि वैश्विक प्रबंधित वस्तुओं के समय विनाशक (/clr के साथ संकलित फ़ाइलों में रखे गैर-रेफ कक्षाएं) ICLRPolicyManager->SetTimeout(OPR_ProcessExit, <timeout>) का उपयोग करके नियंत्रित किया जा सकता है।

एक अनुमान hazarding, मुझे लगता है कि कारण वैश्विक देशी कंस्ट्रक्टर्स/विनाशकर्ता "सामान्य रूप से" में कार्य DLL परिदृश्य में (के रूप में मैं उम्मीद करेंगे व्यवहार कर के रूप में परिभाषित) देशी कार्यों पर LoadLibrary और GetProcAddress उपयोग करने की अनुमति है। इस प्रकार मैं उम्मीद करता हूं कि भविष्य में यह भविष्य में बदलने के लिए अपेक्षाकृत सुरक्षित नहीं है, लेकिन आधिकारिक स्रोतों/दस्तावेज़ीकरण से किसी तरह की पुष्टि/अस्वीकार करने की सराहना करता है।

अद्यतन 2:

विजुअल स्टूडियो 2012 में (एक्सप्रेस और प्रीमियम संस्करण के साथ परीक्षण किया है, मैं दुर्भाग्य से इस मशीन पर पहले के संस्करणों के लिए पहुँच नहीं है)। इसे कमांड लाइन (उपरोक्त उल्लिखित भवन) पर उसी तरह काम करना चाहिए, लेकिन यहां आईडीई के भीतर से पुन: उत्पन्न करने का तरीका बताया गया है।

बिल्डिंग CLRHost.exe:

  1. फ़ाइल -> नया प्रोजेक्ट
  2. विजुअल C++ -> Win32 -> Win32 कंसोल अनुप्रयोग (नाम परियोजना "CLRHost")
  3. आवेदन सेटिंग्स -> अतिरिक्त विकल्प -> खाली परियोजना
  4. प्रेस "समाप्त करें"
  5. समाधान एक्सप्लोरर में स्रोत फ़ाइलों पर राइट क्लिक करें। जोड़ें -> नया आइटम -> दृश्य सी ++ -> सी ++ फ़ाइल। इसे CLRHost.cpp नाम दें और पोस्ट से CLRHost.cpp की सामग्री पेस्ट करें।
  6. परियोजना -> गुण। कॉन्फ़िगरेशन गुण -> सी/सी ++ -> कोड जनरेशन -> "सी ++ अपवादों को सक्षम करें" में "एसईएच अपवाद (/ ईएचए)" और "मूल रनटाइम चेक" के साथ "डिफ़ॉल्ट"
  7. बिल्ड करें।

बिल्डिंग CLR.DLL:

  1. फ़ाइल -> नया प्रोजेक्ट
  2. विजुअल C++ -> CLR -> कक्षा लाइब्रेरी (नाम परियोजना "CLR")
  3. सभी स्वत: जनरेट की फ़ाइलें हटाएँ
  4. परियोजना -> गुण। कॉन्फ़िगरेशन गुण -> सी/सी ++ -> प्रीकंपिल्ड हेडर -> प्रीकंपिल्ड हेडर। "प्रीकंपील्ड हेडर का उपयोग न करें" में बदलें।
  5. समाधान एक्सप्लोरर में स्रोत फ़ाइलों पर राइट क्लिक करें। जोड़ें -> नया आइटम -> दृश्य सी ++ -> सी ++ फ़ाइल। इसे CLR.cpp नाम दें और पोस्ट से CLR.cpp की सामग्री पेस्ट करें।
  6. Native.cpp नामक एक नई सी ++ फ़ाइल जोड़ें और पोस्ट से कोड पेस्ट करें।
  7. समाधान एक्सप्लोरर में "Native.cpp" पर राइट क्लिक करें और गुण चुनें। बदलें सी/सी ++ -> सामान्य -> ​​सामान्य भाषा रनटाइम समर्थन "कोई सामान्य भाषा रनटाइम समर्थन"
  8. प्रोजेक्ट -> गुण -> डिबगिंग। CLRhost.exe को इंगित करने के लिए "कमांड" को इंगित करने के लिए "कमांड तर्क" को "$ (लक्ष्यपैथ)" पर उद्धरण, "डिबगर प्रकार" को "मिश्रित"
  9. बनाएं और डीबग करें।

    > clr.dll!Global::~Global() Line 11 C++ 
        clr.dll!`dynamic atexit destructor for 'g''() + 0xd bytes C++ 
        clr.dll!_CRT_INIT(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 416 C 
        clr.dll!__DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 522 + 0x11 bytes C 
        clr.dll!_DllMainCRTStartup(void * hDllHandle, unsigned long dwReason, void * lpreserved) Line 472 + 0x11 bytes C 
        [email protected]() + 0x136 bytes 
        [email protected]() + 0xad bytes 
        [email protected]() + 0x14 bytes 
        [email protected]() + 0x141 bytes  
        [email protected]() + 0x74 bytes 
        kernel32.dll!74e37a0d()  
        mscoreei.dll!RuntimeDesc::ShutdownAllActiveRuntimes() + 0x10e bytes  
        [email protected]() + 0x27 bytes 
        [email protected]() + 0x94 bytes 
        msvcr110d.dll!___crtCorExitProcess() + 0x3a bytes 
        msvcr110d.dll!___crtExitProcess() + 0xc bytes 
        msvcr110d.dll!__unlockexit() + 0x27b bytes 
        msvcr110d.dll!_exit() + 0x10 bytes 
        CLRHost.exe!__tmainCRTStartup() Line 549 C 
        CLRHost.exe!wmainCRTStartup() Line 377 C 
        [email protected]@12() + 0x12 bytes  
        [email protected]() + 0x27 bytes 
        [email protected]() + 0x1b bytes  
    

    (एक स्टैंडअलोन निष्पादन योग्य मैं एक स्टैक ट्रेस है कि बहुत हंस Passant द्वारा मनाया के समान है मिल के रूप में चल रहा है, हालांकि:

ग्लोबल के नाशक में एक ब्रेकपाइंट रखने निम्नलिखित स्टैक ट्रेस देता है यह सीआरटी की कामयाब संस्करण) का उपयोग नहीं कर रहा है:

> clrexe.exe!Global::~Global() Line 10 C++ 
    clrexe.exe!`dynamic atexit destructor for 'g''() + 0xd bytes C++ 
    msvcr110d.dll!__unlockexit() + 0x1d3 bytes 
    msvcr110d.dll!__cexit() + 0xe bytes  
    [Managed to Native Transition] 
    clrexe.exe!<CrtImplementationDetails>::LanguageSupport::_UninitializeDefaultDomain(void* cookie) Line 577 C++ 
    clrexe.exe!<CrtImplementationDetails>::LanguageSupport::UninitializeDefaultDomain() Line 594 + 0x8 bytes C++ 
    clrexe.exe!<CrtImplementationDetails>::LanguageSupport::DomainUnload(System::Object^ source, System::EventArgs^ arguments) Line 628 C++ 
    clrexe.exe!<CrtImplementationDetails>::ModuleUninitializer::SingletonDomainUnload(System::Object^ source, System::EventArgs^ arguments) Line 273 + 0x6e bytes C++ 
    [email protected]@12() + 0x12 bytes  
    [email protected]() + 0x27 bytes 
    [email protected]() + 0x1b bytes  
+1

आप CLRHost.exe के साथ काफी अटक गए हैं, सीएलआर लोड करने और इसे फिर से कॉन्फ़िगर करने की अनुमति देने के लिए आपके प्रोग्राम का एंट्रीपॉइंट अप्रबंधित होना चाहिए। यदि आप एक निष्पादन योग्य है तो यह आपके EXE में एम्बेडेड संसाधनों से असेंबली लोड करने के लिए IHostAssemblyStore हैक कर सकता है। एक साधारण सेटअप के साथ प्रतिस्पर्धी बनाने के लिए मुश्किल है।exe –

+0

@ हंसपैसेंट: एक एकल EXE मेरी मुख्य चिंता नहीं है (वास्तविक आवेदन जो मेरा प्रश्न पहले से ही कई डीएलएल पर निर्भर करता है), मुझे इसके मूल भाग में रूचि है जैसे कि यह मानक मूल में होगा आवेदन (और मेजबान EXE नहीं होने से डीबगिंग इत्यादि आसान हो जाएगा)। अधिकांशतः मैं यह जानना चाहता हूं कि मैं कहां पढ़ सकता हूं कि यह लोड/होस्ट किए जाने के आधार पर अलग-अलग व्यवहार क्यों करता है। मुझे एक ऐसे दृष्टिकोण का उपयोग करने में असहज महसूस होता है जिसे मैं नहीं जानता (क्या सीआरटी/संकलक के अपडेट हो सकता है अचानक होस्टेड परिदृश्य EXE की तरह व्यवहार करता है?) – user786653

+0

जो मुझे नहीं मिल रहा है वह है कि स्टैंडअलोन EXE में विनाशक रन ProcessExit के दौरान एक फाइनलाइज़र के रूप में, लेकिन होस्टेड परिदृश्य में विनाशक डीएलएल अनलोड के दौरान चलता है (ExecuteInDefaultAppDomain रिटर्न और क्लॉहोस्ट वैश्विक विनाशक के बिना जारी रहता है) यानी यह एक अंतिमकर्ता (जहां तक ​​मैं कह सकता हूं) के रूप में नहीं चल रहा है। – user786653

उत्तर

8

पहले रास्ते से बाहर आसान सवाल हो रही है:

सीएलआर अनुकूलन के लिए एक अच्छा संसाधन Steven Pratschner's book है "माइक्रोसॉफ्ट .NET फ्रेमवर्क सामान्य भाषा रनटाइम को अनुकूलित करना"। सावधान रहें कि यह पुराना है, होस्टिंग इंटरफेस .NET 4.0 में बदल गया है। एमएसडीएन इसके बारे में ज्यादा कुछ नहीं कहता है लेकिन होस्टिंग इंटरफेस अच्छी तरह से प्रलेखित हैं।

आप डीबगर सेटिंग को बदलकर डीबगिंग को सरल बना सकते हैं, "ऑटो" से "प्रबंधित" या "मिश्रित" प्रकार को बदल सकते हैं।

ध्यान दें कि आपकी 3000 एमसीसी नींद किनारे पर है, आपको 5000 एमसीसी के साथ परीक्षण करना चाहिए। यदि C++ क्लास कोड में दिखाई देता है जो प्रभाव में/clr के साथ संकलित होता है, #pragma पर अप्रबंधित होने के साथ भी आपको फाइनलज़र थ्रेड टाइमआउट को ओवरराइड करने की आवश्यकता होगी। नेट 3.5 एसपी 1 CLR संस्करण पर परीक्षण किया गया है, तो निम्न कोड अच्छी तरह से काम नाशक पूरा होने से चलाने के लिए पर्याप्त समय देने के लिए:,

ICLRControl* pControl; 
if (FAILED(hr = pRuntimeHost->GetCLRControl(&pControl))) { 
    goto out; 
} 
ICLRPolicyManager* pPolicy; 
if (FAILED(hr = pControl->GetCLRManager(__uuidof(ICLRPolicyManager), (void**)&pPolicy))) { 
    goto out; 
} 
hr = pPolicy->SetTimeout(OPR_FinalizerRun, 60000); 
pPolicy->Release(); 
pControl->Release(); 

मैं एक उचित समय के रूप में एक मिनट उठाया के रूप में आवश्यक tweak। ध्यान दें कि एमएसडीएन दस्तावेज़ में एक बग है, यह OPR_FinalizerRun को अनुमत मान के रूप में नहीं दिखाता है लेकिन यह वास्तव में ठीक से काम करता है। फाइनलजर थ्रेड टाइमआउट को सेट करने से यह भी सुनिश्चित होता है कि एक प्रबंधित फ़ाइनलाइज़र समय समाप्त नहीं होगा जब यह अप्रत्यक्ष रूप से एक अप्रबंधित सी ++ वर्ग, एक बहुत ही सामान्य परिदृश्य को नष्ट कर देता है।

एक चीज जो आप देखेंगे जब आप इस कोड को CLRHost के साथ संकलित करते हैं/clr के साथ यह है कि GetCLRManager() को कॉल HOST_E_INVALIDOPERATION रिटर्न कोड के साथ विफल हो जाएगा। आपके CLRHost.exe को निष्पादित करने के लिए लोड किया गया डिफ़ॉल्ट सीएलआर होस्ट आपको नीति को ओवरराइड करने नहीं देगा। तो आप सीएलआर की मेजबानी के लिए एक समर्पित EXE रखने के साथ बहुत अटक गए हैं।

जब मैं CLRHost एक मिश्रित-मोड विधानसभा लोड होने से इस परीक्षण किया है, कॉल स्टैक इस तरह देखा जब नाशक पर एक ब्रेकपाइंट की स्थापना:

CLRClient.dll!Global::~Global() Line 24 C++ 
[Managed to Native Transition] 
CLRClient.dll!<Module>[email protected]@YMXXZ() + 0x1b bytes  
CLRClient.dll!_exit_callback() Line 449 C++ 
CLRClient.dll!<CrtImplementationDetails>::LanguageSupport::_UninitializeDefaultDomain(void* cookie = <undefined value>) Line 753 C++ 
CLRClient.dll!<CrtImplementationDetails>::LanguageSupport::UninitializeDefaultDomain() Line 775 + 0x8 bytes C++ 
CLRClient.dll!<CrtImplementationDetails>::LanguageSupport::DomainUnload(System::Object^ source = 0x027e1274, System::EventArgs^ arguments = <undefined value>) Line 808 C++ 
msvcm90d.dll!<CrtImplementationDetails>.ModuleUninitializer.SingletonDomainUnload(object source = {System.AppDomain}, System.EventArgs arguments = null) + 0xa1 bytes 
    // Rest omitted 

ध्यान दें कि इससे आपके प्रश्न का में अपनी टिप्पणियों को विपरीत है । कोड सीआरटी (msvcm90.dll) के प्रबंधित संस्करण द्वारा ट्रिगर किया गया है। और यह कोड एक समर्पित धागे पर चलता है, जो एक एपडोमेन को अनलोड करने के लिए सीएलआर द्वारा शुरू किया जाता है। आप इसके लिए स्रोत कोड vc/crt/src/mstartup.cpp स्रोत कोड फ़ाइल में देख सकते हैं।


दूसरे परिदृश्य तब होता है जब सी ++ वर्ग है कि प्रभाव में बिना/CLR संकलित किया गया है और मिश्रित मोड विधानसभा में लिंक किया गया एक स्रोत कोड फ़ाइल का हिस्सा है। संकलक तब विनाशक को कॉल करने के लिए सामान्य एटएक्सिट() हैंडलर का उपयोग करता है, जैसे कि यह आमतौर पर एक अप्रबंधित निष्पादन योग्य में होता है। इस मामले में जब डीएलएल को प्रोग्राम समाप्त होने पर विंडोज़ द्वारा अनलोड किया जाता है और सीआरटी के प्रबंधित संस्करण बंद हो जाते हैं।

उल्लेखनीय है कि यह के बाद होता है सीएलआर बंद हो जाता है और यह कि विनाशक प्रोग्राम के स्टार्टअप थ्रेड पर चलता है। तदनुसार, सीएलआर टाइमआउट तस्वीर से बाहर हैं और विनाशक जितना चाहें उतना समय ले सकता है। स्टैक ट्रेस का सार है: हालांकि

CLRClient.dll!Global::~Global() Line 12 C++ 
CLRClient.dll!`dynamic atexit destructor for 'g''() + 0xd bytes C++ 
    // Confusingly named functions elided 
    //... 
CLRHost.exe!__crtExitProcess(int status=0x00000000) Line 732 C 
CLRHost.exe!doexit(int code=0x00000000, int quick=0x00000000, int retcaller=0x00000000) Line 644 + 0x9 bytes C 
CLRHost.exe!exit(int code=0x00000000) Line 412 + 0xd bytes C 
    // etc.. 

यह एक कोने मामले कि केवल तब होगा जब स्टार्टअप EXE अप्रबंधित है। जैसे ही EXE प्रबंधित होता है, यह AppDomain पर विनाशकों को चलाएगा। अनलोड करें, भले ही वे कोड में दिखाई दें जो बिना/clr के संकलित किए गए थे। तो आपके पास अभी भी टाइमआउट समस्या है। एक अप्रबंधित EXE होने के कारण बहुत असामान्य नहीं है, उदाहरण के लिए यह होगा जब आप [ComVisible] प्रबंधित कोड लोड करते हैं। लेकिन यह आपके परिदृश्य की तरह नहीं लगता है, आप CLRHost से फंस गए हैं।

+0

आपके उत्तरों के लिए धन्यवाद। मैंने होस्टेड उदाहरण में टाइमआउट को सक्रिय रूप से नहीं बदला है, ऐसा लगता है कि डीएनएल अनलोड के दौरान विनाशक चलाए जाते हैं, हालांकि इसे स्थापित करने से प्रबंधित विनाशकों को लंबे समय तक (अपेक्षित) चलाने की अनुमति मिलती है, जिससे टाइमआउट सेट किया जा सकता है। 10 एमएस अभी भी विनाशक चलाने देता है। भले ही आप सी ++/सीएलआई (कम से कम एसओ पर) का सबसे बड़ा अधिकार प्रतीत होता है, फिर भी मैं प्रश्न को अद्यतन करने और अधिक संतोषजनक संकल्प के करीब आने की उम्मीद में एक बक्षीस देने की योजना बना रहा हूं। – user786653

+0

ओह, मैं पूरी तरह से पढ़ता हूं कि वास्तव में आप ICLRPolicyManager का उपयोग नहीं करते हैं। यह कुछ खुदाई करने जा रहा है, बक्षीस के लिए जाओ। –

+0

मैं सवाल अद्यतन करता हूं। मैंने अभी भी विजुअल सी ++ 2010 एक्सप्रेस स्थापित किया है और व्यवहार वीसी ++ 2012 के समान ही कॉल स्टैक के समान है। – user786653

1

"यह दस्तावेज कहां है/मैं इस विषय पर खुद को और शिक्षित कैसे कर सकता हूं?" का उत्तर देने के लिए प्रश्न: यदि आप http://www.microsoft.com/en-us/download/details.aspx?id=4917 से Shared Source Common Language Infrastructure (उर्फ एसएससीएलआई) डाउनलोड और चेक आउट करते हैं तो आप समझ सकते हैं कि यह कैसे काम करता है (या कम से कम फ्रेमवर्क 2 के लिए काम करता है)।

जब आपके पास फ़ाइलें निकाला है, तो आप gcEE.ccp ("कचरा संग्रहण निष्पादन इंजन") में मिलेगा यह:

#define FINALIZER_TOTAL_WAIT 2000 

जो 2 सेकंड के इस प्रसिद्ध डिफ़ॉल्ट मान परिभाषित करता है। तुम भी एक ही फाइल में इस देखेंगे:

BOOL GCHeap::FinalizerThreadWatchDogHelper() 
{ 
    // code removed for brevity ... 
    DWORD totalWaitTimeout; 
    totalWaitTimeout = GetEEPolicy()->GetTimeout(OPR_FinalizerRun); 
    if (totalWaitTimeout == (DWORD)-1) 
    { 
     totalWaitTimeout = FINALIZER_TOTAL_WAIT; 
    } 

कि तुम बताओ, निष्पादन इंजन OPR_FinalizerRun नीति का पालन करना होगा, अगर परिभाषित जो EClrOperation Enumeration में मूल्य के अनुरूप हैं। GetEEPolicy को eePolicy.h & eePolicy.cpp में परिभाषित किया गया है।

+0

उत्तर के लिए धन्यवाद। मैंने एसएससीएलआई में पहले से ही (संक्षेप में) देखा है, लेकिन जहां तक ​​मैं कह सकता हूं, प्रबंधित और देशी कोड के बीच इंटरप्ले सीआरटी द्वारा पूरी तरह से निर्धारित किया जाता है। अर्थात। क्या मूल वैश्विक वस्तु के लिए विनाशक एपडोमेन अनलोड के दौरान या डीएलएल अनलोड के दौरान अंतिम रूप में चलाता है, सीएलआर पर निर्भर नहीं है। – user786653

संबंधित मुद्दे