Λαμβάνετε προειδοποιητικά μηνύματα πρόγραμμα σύνδεσης κατά τη δημιουργία διαχειριζόμενων επεκτάσεις για C++ DLL έργα

Συμπτώματα

Λαμβάνετε ένα από τα ακόλουθα μηνύματα λάθους κατά τη μεταγλώττιση ή τη σύνδεση:
LNK2001 σφάλμα εργαλεία πρόγραμμα σύνδεσης
"μη επιλυμένη εξωτερικών σύμβολο"σύμβολο""

Εργαλεία πρόγραμμα σύνδεσης προειδοποίηση LNK4210
'. Υπάρχει ενότητα CRT; ενδέχεται να υπάρχουν ανεπίλυτες εκκινεί την στατική ή teminators'You λαμβάνουν προειδοποιήσεις πρόγραμμα σύνδεσης κατά τη δημιουργία διαχειριζόμενων επεκτάσεις για C++ DLL έργα

Εργαλεία πρόγραμμα σύνδεσης προειδοποίηση LNK4243
' DLL που περιέχει αντικείμενα μεταγλωττιστεί με/clr δεν είναι συνδεδεμένο με /NOENTRY; εικόνα μπορεί να μην εκτελούνται σωστά '.
Αυτές οι προειδοποιήσεις ενδέχεται να προκύψουν κατά τις ακόλουθες περιπτώσεις:
  • Όταν κάνετε μεταγλώττιση σύνδεση αντικειμένων με το διακόπτη /clr .
  • Όταν δημιουργείτε ένα από τα ακόλουθα έργα: πρότυπο υπηρεσίας Web ASP.NET. Πρότυπο βιβλιοθήκη κλάσης. ή, τα Windows ελέγχουν το πρότυπο βιβλιοθήκης.
  • Όταν έχετε προσθέσει κώδικα που χρησιμοποιεί καθολικές μεταβλητές ή κλάσεις μητρική (δηλαδή, δεν __gc ή __value) με μέλη στατικά δεδομένα. Για παράδειγμα, η βιβλιοθήκη ActiveX προτύπων (ATL), Microsoft Foundation κλάσεις (MFC) και τις κλάσεις χρόνου εκτέλεσης C (CRT)
Σημείωση: ενδέχεται να λάβετε τα σφάλματα LNK2001 και LNK4210 με έργα που δεν επηρεάζονται από το ζήτημα που περιγράφεται σε αυτό το άρθρο. Ωστόσο, επηρεάζεται από το ζήτημα που περιγράφεται σε αυτό το άρθρο εάν επίλυση ενός LNK2001 το έργο σίγουρα ή προειδοποίηση LNK4210 οδηγεί σε μια προειδοποίηση LNK4243 ή εάν η σύνδεση του έργου δημιουργεί μια προειδοποίηση LNK4243.

Αιτία

Τα ακόλουθα έργα δημιουργούνται από προεπιλογή ως μια βιβλιοθήκη δυναμικής σύνδεσης (DLL) χωρίς οποιαδήποτε σύνδεσης σε εγγενή βιβλιοθήκες (όπως το CRT ATL ή MFC) και χωρίς καθολικών μεταβλητών ή κλάσεις μητρική με μέλη στατικά δεδομένα:
  • Πρότυπο υπηρεσία Web του ASP.NET
  • Πρότυπο βιβλιοθήκης κλάσης
  • Πρότυπο βιβλιοθήκης ελέγχου των Windows
Εάν προσθέτετε τον κώδικα που χρησιμοποιεί καθολικές μεταβλητές ή κλάσεις μητρική με μέλη στατικά δεδομένα (για παράδειγμα, οι βιβλιοθήκες ATL MFC και CRT χρησιμοποιεί καθολικές μεταβλητές), θα λάβετε μηνύματα λάθους πρόγραμμα σύνδεσης κατά τη μεταγλώττιση. Όταν συμβεί αυτό, πρέπει να προσθέσετε κώδικα για την προετοιμασία με μη αυτόματο τρόπο τις στατικές μεταβλητές. Για περισσότερες πληροφορίες σχετικά με τον τρόπο για να το κάνετε αυτό, ανατρέξτε στην ενότητα "Προτεινόμενη αντιμετώπιση" αυτού του άρθρου.

Για δική σας διευκόλυνση, αυτό το άρθρο αναφέρεται σε καθολικές μεταβλητές και μέλη στατικά δεδομένα εγγενή κλάσεων ως "statics" ή "στατικών μεταβλητών" από αυτό το σημείο προς τα εμπρός.

Αυτό το ζήτημα προκαλείται από το μεικτό ζήτημα κατά τη φόρτωση του DLL. Μεικτή dll (δηλαδή, DLL που περιέχει τόσο διαχειριζόμενες όσο και εγγενή κώδικα) μπορεί να αντιμετωπίσετε σενάρια αδιέξοδο, υπό ορισμένες συνθήκες, όταν έχουν φορτωθεί στο χώρο διεύθυνσης της διεργασίας, ειδικά όταν το σύστημα βρίσκεται υπό μεγάλο φόρτο. Το πρόγραμμα σύνδεσης μηνύματα λάθους που αναφέρθηκε προηγουμένως ενεργοποιήθηκαν με το πρόγραμμα σύνδεσης για να βεβαιωθείτε ότι οι πελάτες είναι ενήμεροι για την πιθανή αδιέξοδη κατάσταση και τις λύσεις που περιγράφονται σε αυτό το έγγραφο. Για μια λεπτομερή περιγραφή του προβλήματος μεικτών φόρτωσης DLL, ανατρέξτε την ακόλουθη λευκή βίβλο:
Πρόβλημα κατά τη φόρτωση DLL μεικτή
http://msdn2.microsoft.com/en-us/library/aa290048(vs.71).aspx

Προτεινόμενη αντιμετώπιση

Διαχείριση επεκτάσεων για έργα C++ που δημιουργούνται ως αρχεία DLL από προεπιλογή δεν συνδεθείτε σε εγγενή βιβλιοθήκες C/C++, όπως η βιβλιοθήκη (CRT) χρόνου εκτέλεσης C, ATL ή MFC και δεν χρησιμοποιείτε οποιεσδήποτε στατικές μεταβλητές. Επιπλέον, τις ρυθμίσεις του έργου καθορίσετε ότι τα αρχεία DLL θα πρέπει να συνδέονται με ενεργοποιημένη την επιλογή /NOENTRY .

Αυτό γίνεται επειδή η σύνδεση με ένα σημείο καταχώρησης προκαλεί διαχειριζόμενου κώδικα για εκτέλεση στη διάρκεια DllMain, που δεν είναι ασφαλής (βλέπε DllMain για το περιορισμένο σύνολο που μπορείτε να κάνετε κατά τη διάρκεια της εφαρμογής).

Ένα DLL χωρίς ένα σημείο καταχώρησης με κανένα τρόπο να προετοιμάσει μεταβλητές στατική εκτός από πολύ απλή τύπους όπως ακέραιους αριθμούς. Δεν έχουν συνήθως στατικών μεταβλητών στο /NOENTRY DLL.

Οι βιβλιοθήκες ATL MFC και CRT όλα εξαρτώνται από στατικών μεταβλητών, έτσι επίσης δεν μπορείτε να χρησιμοποιήσετε αυτές τις βιβλιοθήκες από εντός αυτών των DLL χωρίς πρώτα τις τροποποιήσεις.

Εάν το αρχείο DLL μεικτής λειτουργίας πρέπει να χρησιμοποιήσει statics ή βιβλιοθήκες που εξαρτώνται από το statics (όπως ATL, MFC ή CRT), στη συνέχεια, πρέπει να τροποποιήσετε το αρχείο DLL έτσι ώστε το statics προετοιμάζονται με μη αυτόματο τρόπο.

Είναι το πρώτο βήμα για την προετοιμασία με μη αυτόματο τρόπο για να βεβαιωθείτε ότι απενεργοποιήσετε τον κώδικα προετοιμασίας αυτόματης, που είναι μη ασφαλές με μεικτή dll και μπορεί να προκαλέσει αδιέξοδο. Για να απενεργοποιήσετε τον κώδικα προετοιμασίας, ακολουθήστε τα βήματα.

Καταργήστε το σημείο εισόδου του διαχειριζόμενο DLL

  1. Σύνδεση με /NOENTRY. Στην Εξερεύνηση λύσεων, κάντε δεξιό κλικ στον κόμβο του έργου, κάντε κλικ στο κουμπί Ιδιότητες. Στο πλαίσιο διαλόγου Σελίδες ιδιοτήτων, κάντε κλικ στην επιλογή πρόγραμμα σύνδεσης, κάντε κλικ στην επιλογή γραμμή εντολώνκαι, στη συνέχεια, προσθέστε αυτόν το διακόπτη στο πεδίο Πρόσθετες επιλογές.
  2. Σύνδεση msvcrt.lib. Στο πλαίσιο διαλόγου Σελίδες ιδιοτήτων , κάντε κλικ στο κουμπί
    Πρόγραμμα σύνδεσης, κάντε κλικ στο κουμπί εισόδου., και στη συνέχεια να προσθέσετε msvcrt.lib τις Επιπλέον εξαρτήσεις
    property.
  3. Κατάργηση nochkclr.obj. Στη σελίδα εισόδου (ίδια σελίδα με το προηγούμενο βήμα), καταργήστε nochkclr.obj από την ιδιότητα Επιπλέον εξαρτήσεις .
  4. Σύνδεση με το CRT. Στη σελίδα εισόδου (ίδια σελίδα με το προηγούμενο βήμα), προσθέστε __DllMainCRTStartup@12 στην ιδιότητα Αναφορές σύμβολο δύναμης.

    Εάν χρησιμοποιείτε τη γραμμή εντολών, καθορίστε τις παραπάνω ρυθμίσεις έργου με τα εξής:
    LINK /NOENTRY msvcrt.lib /NODEFAULTLIB:nochkclr.obj /INCLUDE:__DllMainCRTStartup@12

Τροποποιήστε τα στοιχεία που καταναλώνουν το DLL για μη αυτόματη Initializiation

Αφού καταργήσετε το σημείο εισόδου ρητή, πρέπει να τροποποιήσετε τα στοιχεία που καταναλώνουν το DLL για μη αυτόματη προετοιμασία, ανάλογα με τον τρόπο που έχει υλοποιηθεί το αρχείο DLL:
  • Το αρχείο DLL καταχωρείται με εξαγωγές DLL (__declspec(dllexport)) και σας στους καταναλωτές δεν είναι δυνατό να χρησιμοποιούν διαχειριζόμενο κώδικα, εάν είναι συνδεδεμένα με το αρχείο DLL στατικά ή δυναμικά.
  • Το αρχείο DLL είναι βασισμένη σε COM DLL.
  • Τους καταναλωτές για το αρχείο DLL σας μπορούν να χρησιμοποιούν διαχειριζόμενο κώδικα και το αρχείο DLL που περιέχει είτε εξαγωγές DLL ή διαχείριση σημείων εισόδου.

Τροποποίηση DLL που εισάγετε χρησιμοποιώντας εξαγωγές DLL και τους καταναλωτές, που δεν είναι δυνατό να χρησιμοποιούν διαχειριζόμενο κώδικα

Για να τροποποιήσετε τα αρχεία DLL που εισάγετε χρησιμοποιώντας εξαγωγές dll (__declspec(dllexport)) και τους καταναλωτές, που δεν είναι δυνατό να χρησιμοποιούν διαχειριζόμενο κώδικα, ακολουθήστε τα εξής βήματα:
  1. Προσθέστε δύο νέες εξαγωγές στο αρχείο DLL σας, όπως φαίνεται στον ακόλουθο κώδικα:
    // init.cpp
    #include <windows.h>
    #include <_vcclrit.h>

    // Call this function before you call anything in this DLL.
    // It is safe to call from multiple threads; it is not reference
    // counted; and is reentrancy safe.

    __declspec(dllexport) void __cdecl DllEnsureInit(void)
    {
    // Do nothing else here. If you need extra initialization steps,
    // create static objects with constructors that perform initialization.
    __crt_dll_initialize();
    // Do nothing else here.
    }

    // Call this function after this whole process is totally done
    // calling anything in this DLL. It is safe to call from multiple
    // threads; is not reference counted; and is reentrancy safe.
    // First call will terminate.

    __declspec(dllexport) void __cdecl DllForceTerm(void)
    {
    // Do nothing else here. If you need extra terminate steps,
    // use atexit.
    __crt_dll_terminate();
    // Do nothing else here.
    }

    Σημείωση Στο Visual C++ 2005, πρέπει να προσθέσετε την κοινή γλώσσα χρόνου εκτέλεσης υποστήριξη επιλογή μεταγλωττιστή (/clr:oldSyntax) για μεταγλωττιστεί με επιτυχία το προηγούμενο δείγμα κώδικα. Για να προσθέσετε επιλογή μεταγλωττιστή υποστήριξης χρόνου εκτέλεσης κοινής γλώσσας, ακολουθήστε τα εξής βήματα:

    1. Κάντε κλικ στο έργοκαι στη συνέχεια κάντε κλικ στο κουμπί

      Όνομα_έργου ιδιότητες.



      Σημείωση Όνομα_έργου είναι ένα σύμβολο κράτησης θέσης για το όνομα του έργου.
    2. Αναπτύξτε το στοιχείο Ρύθμισης παραμέτρων ιδιοτήτωνκαι, στη συνέχεια, κάντε κλικ στο κουμπί

      Γενικά.

    3. Στο δεξιό τμήμα του παραθύρου, κάντε κλικ για να επιλέξετε κοινή υποστήριξη χρόνου εκτέλεσης γλώσσας, παλιά σύνταξη (/ clr:oldSyntax) με το

      Χρόνος εκτέλεσης κοινής γλώσσας υποστηρίζει ρυθμίσεις έργου.
    4. Κάντε κλικ στο κουμπί

      Εφαρμογή, και στη συνέχεια κάντε κλικ στο κουμπί OK.

    Για περισσότερες πληροφορίες σχετικά με κοινές επιλογές μεταγλωττιστή υποστήριξης χρόνου εκτέλεσης γλώσσας, επισκεφθείτε την ακόλουθη τοποθεσία του Microsoft Developer Network (MSDN) στο Web:

    Αυτά τα βήματα ισχύουν για ολόκληρο το άρθρο.
  2. Αρχείο DLL σας μπορεί να έχει πολλούς καταναλωτές. Εάν έχει πολλούς καταναλωτές, προσθέστε τον ακόλουθο κώδικα στο αρχείο DLL .def στην ενότητα "Εξαγωγή":
    DllEnsureInitPRIVATEDllForceTermPRIVATE

    Εάν δεν προσθέσετε αυτές τις γραμμές και, εάν έχετε δύο αρχεία DLL που εξαγάγετε λειτουργίες, η εφαρμογή που συνδέεται με το αρχείο DLL θα έχουν σφάλματα σύνδεσης. Συνήθως, οι λειτουργίες εξαγωγής έχουν τα ίδια ονόματα. Σε περίπτωση multiconsumer, κάθε καταναλωτή μπορούν να συνδεθούν στατικά ή δυναμικά με το αρχείο DLL.
  3. Εάν ο καταναλωτής συνδέεται στατικά με το DLL, πριν να χρησιμοποιήσετε το αρχείο DLL την πρώτη φορά ή μπορείτε να χρησιμοποιήσετε οτιδήποτε εξαρτάται στην εφαρμογή σας, προσθέστε την παρακάτω κλήση:
    // Snippet 1
    typedef void (__stdcall *pfnEnsureInit)(void);
    typedef void (__stdcall *pfnForceTerm)(void);

    {
    // ... initialization code
    HANDLE hDll=::GetModuleHandle("mydll.dll");
    If(!hDll)
    {
    // Exit, return; there is nothing else to do.
    }
    pfnEnsureInit pfnDll=::( pfnEnsureInit) GetProcAddress(hDll,
    "DllEnsureInit");
    if(!pfnDll)
    {
    // Exit, return; there is nothing else to do.
    }

    pfnDll();

    // ... more initialization code
    }

  4. Μετά από την τελευταία χρήση του αρχείου DLL της εφαρμογής σας, προσθέστε τον ακόλουθο κώδικα:
    // Snippet 2
    {
    // ... termination code
    HANDLE hDll=::GetModuleHandle("mydll.dll");
    If(!hDll)
    {
    // exit, return; there is nothing else to do
    }
    pfnForceTerm pfnDll=::( pfnForceTerm) GetProcAddress(hDll,
    "DllForceTerm");
    if(!pfnDll)
    {
    // exit, return; there is nothing else to do
    }

    pfnDll();

    // ... more termination code
    }

  5. Εάν ο καταναλωτής συνδέεται δυναμικά με το DLL, εισαγωγή κώδικα ως εξής:
    • Εισαγωγή τμήματος 1 (ανατρέξτε στο βήμα 3) αμέσως μετά την πρώτη Φόρτωση βιβλιοθήκης για το αρχείο DLL.
    • Εισαγωγή τμήματος 2 (ανατρέξτε στο βήμα 4) αμέσως πριν από το τελευταίο FreeLibrary για το αρχείο DLL.

Για να τροποποιήσετε βασισμένη σε COM DLL

  • Τροποποιήστε τις λειτουργίες εξαγωγής DLL, DllCanUnloadNow, DllGetClassObject, DllRegisterServerκαι DllUnregisterServer , όπως φαίνεται στον ακόλουθο κώδικα:
    //  Implementation of DLL Exports.
    #include <_vcclrit.h>

    STDAPI DllCanUnloadNow(void)
    {

    if ( _Module.GetLockCount() == 0 )
    {
    __crt_dll_terminate();
    return S_OK;
    }
    else
    {
    return S_FALSE;

    }

    }

    STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
    {
    if ( !( __crt_dll_initialize() ) )
    {
    return E_FAIL;
    }
    else
    {
    return _Module.GetClassObject(rclsid, riid, ppv);
    }
    }

    STDAPI DllRegisterServer(void)
    {
    if ( !( __crt_dll_initialize() ) )
    {
    return E_FAIL;
    }
    // Call your registration code here
    HRESULT hr = _Module.RegisterServer(TRUE)

    return hr;
    }


    STDAPI DllUnregisterServer(void)
    {
    HRESULT hr = S_OK;
    __crt_dll_terminate();

    // Call your unregistration code here
    hr = _Module.UnregisterServer(TRUE);
    return hr;
    }

Τροποποίηση DLL που περιέχει τους καταναλωτές που χρησιμοποιούν διαχειριζόμενο κώδικα και εξαγωγές DLL ή διαχείρισης σημεία εισόδου

Για να τροποποιήσετε το αρχείο DLL που περιέχει τους καταναλωτές που χρησιμοποιούν διαχειριζόμενο κώδικα και dll εξάγει ή σημεία διαχείρισης εισαγωγής, ακολουθήστε τα εξής βήματα:
  1. Υλοποιεί μια διαχειριζόμενη κλάση με στατικό μέλος λειτουργίες για την προετοιμασία και την καταγγελία. Προσθήκη αρχείου .cpp στο έργο σας, η υλοποίηση μιας διαχειριζόμενης κλάσης με στατικών μελών για την προετοιμασία και την καταγγελία:
    // ManagedWrapper.cpp
    // This code verifies that DllMain is not automatically called
    // by the Loader when linked with /noentry. It also checks some
    // functions that the CRT initializes.

    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    #include "_vcclrit.h"

    #using <mscorlib.dll>
    using namespace System;

    public __gc class ManagedWrapper {
    public:
    static BOOL minitialize() {
    BOOL retval = TRUE;
    try {
    retval = __crt_dll_initialize();
    } catch(System::Exception* e) {
    Console::WriteLine(e->Message);
    retval = FALSE;
    }
    return retval;
    }
    static BOOL mterminate() {
    BOOL retval = TRUE;
    try {
    retval = __crt_dll_terminate();
    } catch(System::Exception* e) {
    Console::WriteLine(e->Message);
    retval = FALSE;
    }
    return retval;
    }
    };

    BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID
    lpvReserved) {
    Console::WriteLine(S"DllMain is called...");
    return TRUE;
    } /* DllMain */

  2. Η κλήση αυτές τις συναρτήσεις πριν κάνετε παραπομπή προς το αρχείο DLL και αφού ολοκληρώσετε τη χρήση του. Καλέστε το μέλος της προετοιμασίας και τερματισμού λειτουργίες στο κύριο:
    // Main.cpp
    #using <mscorlib.dll>
    using namespace System;
    using namespace System::Reflection;
    #using "ijwdll.dll";

    int main() {
    int retval = ManagedWrapper::minitialize();
    ManagedWrapper::mterminate();
    }

Οι χρήστες της Visual C++ .NET 2002

Σημείωση: Αν και δεν υπάρχει πρόγραμμα σύνδεσης μήνυμα λάθους LNK4243 στην έκδοση προϊόντος Visual C++ .NET 2002, οι χρήστες της Visual C++ .NET 2002 συνιστάται να ακολουθήσετε τις οδηγίες που αναφέρονται παραπάνω, κατά την ανάπτυξη μεικτών dll.


Την έκδοση του προϊόντος Visual C++ .NET 2003 περιλαμβάνει μια πρόσθετη κεφαλίδα για να κάνετε πιο εύκολη προετοιμασία με μη αυτόματο τρόπο. Για να κάνετε τις λύσεις που παρατίθενται σε αυτό το άρθρο με Visual C++ .NET 2002, πρέπει να προσθέσετε ένα αρχείο κεφαλίδας στο έργο σας, που ονομάζεται _vcclrit.h με το ακόλουθο κείμενο:
/**** _vcclrit.h
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Purpose:
* This file defines the functions and variables used by user
* to initialize CRT and the dll in IJW scenario.
*
****/

#pragma once

#ifdef __cplusplus
extern "C" {
#endif

extern IMAGE_DOS_HEADER __ImageBase;

BOOL WINAPI _DllMainCRTStartup(
HANDLE hDllHandle,
DWORD dwReason,
LPVOID lpreserved
);
#ifdef __cplusplus
}
#endif

#ifdef _cplusplus
#define __USE_GLOBAL_NAMESPACE ::
#else
#define __USE_GLOBAL_NAMESPACE
#endif

// Used to lock
__declspec( selectany ) LONG volatile __lock_handle = 0;

// Init called
__declspec(selectany) BOOL volatile __initialized = FALSE;

// Term called
__declspec( selectany ) BOOL volatile __terminated = FALSE;

__inline BOOL WINAPI __crt_dll_initialize()
{
// Try to make the variable names unique, so that the variables
// do not even clash with macros.
static BOOL volatile (__retval) = FALSE;
static DWORD volatile (__lockThreadId) = 0xffffffff;
DWORD volatile (__currentThreadId) = __USE_GLOBAL_NAMESPACE(GetCurrentThreadId)();
int (__int_var)=0;

// Take Lock; this is needed for multithreaded scenario.
// Additionally, the threads need to wait here to make sure that the dll
// is initialized when they get past this function.
while ( __USE_GLOBAL_NAMESPACE(InterlockedExchange)( &(__lock_handle), 1) == 1 )
{
++(__int_var);
if ((__lockThreadId) == (__currentThreadId))
{
return TRUE;
}
__USE_GLOBAL_NAMESPACE(Sleep)( (__int_var)>1000?100:0 );

// If you hang in this loop, this implies that your
// dllMainCRTStartup is hung on another thread.
// The most likely cause of this is a hang in one of your
// static constructors or destructors.
}
// Note: you do not really need any interlocked stuff here because the
// writes are always in the lock. Only reads are outside the lock.
(__lockThreadId) = (__currentThreadId);
__try {
if ( (__terminated) == TRUE )
{
(__retval) = FALSE;
}
else if ( (__initialized) == FALSE )
{
(__retval) = (_DllMainCRTStartup)( ( HINSTANCE )( &__ImageBase ), DLL_PROCESS_ATTACH, 0 );
(__initialized) = TRUE;
}

} __finally {
// revert the __lockThreadId
(__lockThreadId) = 0xffffffff;
// Release Lock
__USE_GLOBAL_NAMESPACE(InterlockedExchange)(&(__lock_handle),0);
}
return (__retval);
}

__inline BOOL WINAPI __crt_dll_terminate()
{
static BOOL volatile (__retval) = TRUE;
static DWORD volatile (__lockThreadId) = 0xffffffff;
DWORD volatile (__currentThreadId) = __USE_GLOBAL_NAMESPACE(GetCurrentThreadId)();
int (__int_var)=0;

// Take Lock; this lock is needed to keep Terminate
// in sync with Initialize.
while ( __USE_GLOBAL_NAMESPACE(InterlockedExchange)( &(__lock_handle), 1) == 1 )
{
++(__int_var);
if ((__lockThreadId) == (__currentThreadId))
{
return TRUE;
}
__USE_GLOBAL_NAMESPACE(Sleep)( (__int_var)>1000?100:0 );

// If you hang in this loop, this implies that your
// dllMainCRTStartup is hung on another thread. The most likely
// cause of this is a hang in one of your static constructors
// or destructors.
}
// Note: you do not really need any interlocked stuff here because the
// writes are always in the lock. Only reads are outside the lock.
(__lockThreadId) = (__currentThreadId);
__try {
if ( (__initialized) == FALSE )
{
(__retval) = FALSE;
}
else if ( (__terminated) == FALSE )
{
(__retval) = _DllMainCRTStartup( ( HINSTANCE )( &(__ImageBase) ), DLL_PROCESS_DETACH, 0 );
(__terminated) = TRUE;
}
} __finally {
// revert the __lockThreadId
(__lockThreadId) = 0xffffffff;
// Release Lock
__USE_GLOBAL_NAMESPACE(InterlockedExchange)(&(__lock_handle),0);
}
return (__retval);
}

Αναφορές

Για περισσότερες πληροφορίες, κάντε κλικ στον αριθμό του άρθρου παρακάτω, για να προβάλετε το άρθρο της Γνωσιακής Βάσης της Microsoft:

Σφάλμα 309694 : AppDomainUnloaded εξαίρεση όταν χρησιμοποιείτε Διαχείριση επεκτάσεων για στοιχεία της Visual C++

Ιδιότητες

Αναγνωριστικό άρθρου: 814472 - Τελευταία αναθεώρηση: 17 Ιαν 2017 - Αναθεώρηση: 1

Σχόλια