Getting dynamic atexit destructor link error with custom toolset - eh vector destructor

吃可爱长大的小学妹 提交于 2019-12-11 06:39:55

问题


I'm getting a weird linker error when trying to compile against a VS2005 CRT with a Visual Studio 2015 toolset.
The same code compiles perfect on any other toolset version (2005,2010,2012,2013).
The code must compile under VS2005 CRT to properly link with other projects.

How to reproduce: Create a new empty Dynamic Library (dll) project (In VS2015, toolset v140), add a source (.cpp) file:

//1.cpp
#include <string>

static  std::wstring thisWillFail[] = { L"test" };

Change the VC++ include directories and Library directories to:

C:\Program Files (x86)\Microsoft Visual Studio 8\VC\include
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\atlmfc\include
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\include

C:\Program Files (x86)\Microsoft Visual Studio 8\VC\lib
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\atlmfc\lib
C:\Program Files (x86)\Microsoft Visual Studio 8\VC\PlatformSDK\Lib

Then just compile, an you will get this error:

1>StdAfx.obj : error LNK2019: unresolved external symbol "void __stdcall `eh vector destructor iterator'(void *,unsigned int,unsigned int,void (__thiscall*)(void *))" (??_M@YGXPAXIIP6EX0@Z@Z) referenced in function "void __cdecl `dynamic atexit destructor for 'fasdfp''(void)" (??__Ffasdfp@@YAXXZ)

Same will happen if you set the library and include paths to the VS2010 CRT and Windows SDK.

So, why is VS2015 generating this extra function? And most importantly how can i work around this?
The same linker error appears on every static member i have, and a similar one for several classes.


回答1:


In VS2015 there was a major refactoring in the CRT.
Part of that was changing the implementation, and the signature of __ehvec_dtor.
As mentioned here, a simple solution would be to just add the actual implementation.

Simplest way is to add this code to a header file and include it in the stdafx.h:

#if defined __cplusplus_cli
#define CALEETYPE __clrcall
#else
#define CALEETYPE __stdcall
#endif
#define __RELIABILITY_CONTRACT
#define SECURITYCRITICAL_ATTRIBUTE
#define ASSERT_UNMANAGED_CODE_ATTRIBUTE

#if defined __cplusplus_cli
#define CALLTYPE __clrcall 
#elif defined _M_IX86
#define CALLTYPE __thiscall
#else
#define CALLTYPE __stdcall
#endif

__RELIABILITY_CONTRACT
void CALEETYPE __ArrayUnwind(
    void*       ptr,                // Pointer to array to destruct
    size_t      size,               // Size of each element (including padding)
    int         count,              // Number of elements in the array
    void(CALLTYPE *pDtor)(void*)    // The destructor to call
    );

__RELIABILITY_CONTRACT
inline void CALEETYPE __ehvec_ctor(
    void*       ptr,                // Pointer to array to destruct
    size_t      size,               // Size of each element (including padding)
    //  int         count,              // Number of elements in the array
    size_t      count,              // Number of elements in the array
    void(CALLTYPE *pCtor)(void*),   // Constructor to call
    void(CALLTYPE *pDtor)(void*)    // Destructor to call should exception be thrown
    ) {
    size_t i = 0;      // Count of elements constructed
    int success = 0;

    __try
    {
        // Construct the elements of the array
        for (; i < count; i++)
        {
            (*pCtor)(ptr);
            ptr = (char*)ptr + size;
        }
        success = 1;
    }
    __finally
    {
        if (!success)
            __ArrayUnwind(ptr, size, (int)i, pDtor);
    }
}

__RELIABILITY_CONTRACT
SECURITYCRITICAL_ATTRIBUTE
inline void CALEETYPE __ehvec_dtor(
    void*       ptr,                // Pointer to array to destruct
    size_t      size,               // Size of each element (including padding)
    //  int         count,              // Number of elements in the array
    size_t      count,              // Number of elements in the array
    void(CALLTYPE *pDtor)(void*)    // The destructor to call
    ) {
    _Analysis_assume_(count > 0);

    int success = 0;

    // Advance pointer past end of array
    ptr = (char*)ptr + size*count;

    __try
    {
        // Destruct elements
        while (count-- > 0)
        {
            ptr = (char*)ptr - size;
            (*pDtor)(ptr);
        }
        success = 1;
    }
    __finally
    {
        if (!success)
            __ArrayUnwind(ptr, size, (int)count, pDtor);
    }
}


来源:https://stackoverflow.com/questions/44872107/getting-dynamic-atexit-destructor-link-error-with-custom-toolset-eh-vector-des

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!