locked
Strange linker issues with STL/CLR RRS feed

  • Question

  • Hi all, I am having a strange problem with the STL/CLR list class. I get the following linker error if I declare a handle to a list of ints (compiles fine if the list is just a nested object):

    error LNK2020: unresolved token (06000058) cliext.list<int>::Clone

    my code to reproduce this is as follows:

    #pragma once

    #include <cliext/list>

    private ref class TestClass
    {
        cliext::list<int> ^ m_list;
    public:
        TestClass(void);
    };

    I am sure I must have totally misunderstood something - I can't believe that something as simple as this is causing linker errors! I am using visual studio 2008, service pack 1.

    I have had quite a good search around, and haven't found anything useful so far.

    Thanks in advance.

    Thursday, August 21, 2008 4:29 PM

All replies

  • I cannot answer you as to why it is not compiling, but just as a side point try compiling this:

    #include <cliext/list> 
     
    private ref class TestClass 
        cliext::list<int>^ m_list; 
    public: 
      TestClass(void) 
         : m_list( gcnew cliext::list<int>() ) 
      {} 
    }; 

    It doesn't raise the linker error.


    • Edited by Neil Tippett Thursday, August 21, 2008 5:05 PM compiler to linker
    • Proposed as answer by ildjarn Friday, December 19, 2008 7:07 PM
    Thursday, August 21, 2008 5:04 PM
  • Ok, thanks for the clue. I suspect it has something to do with the fact that no code gets generated for a template unless it is actually used. I guess this would not happen because why would you want to declare a member you never use :)

    I am not really clear why the linker cares because we have a handle to the list. Maybe I am thinking of handles as being more like pointers than they really are.
    Friday, August 22, 2008 8:56 AM
  • Right, onto the issue I was actually trying to reproduce in the first place...

    If the list initialisation is moved to the .cpp file, things get more interesting:

    Header file:

    #pragma once

    #include <cliext/list>

    private ref class TestClass
    {
        cliext::list<int> ^ m_list;
    public:
        TestClass(void);
    };

    .cpp file:

    #include "StdAfx.h"
    #include "TestClass.h"

    TestClass::TestClass(void)
    : m_list(gcnew cliext::list<int>())
    {
    }

    Produces this little lot...
    1>------ Build started: Project: LNK2022, Configuration: Debug Win32 ------
    1>Linking...
    1>TestClass.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: cliext.impl.list_impl<int,0>; fields: _Myhead): (0x0400000a).
    1>TestClass.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: cliext.impl.list_impl<int,0>; fields: _Mysize): (0x0400000b).
    1>TestClass.obj : error LNK2022: metadata operation failed (80131188) : Inconsistent field declarations in duplicated types (types: cliext.impl.list_impl<int,0>; fields: _Mygen): (0x0400000c).
    1>TestClass.obj : error LNK2022: metadata operation failed (801311D7) : Differing number of fields in duplicated types (cliext.impl.list_impl<int,0>): (0x02000023).
    1>TestClass.obj : error LNK2022: metadata operation failed (8013118B) : Inconsistent implemented interfaces in duplicated types (types: cliext.impl.list_impl<int,0>; interfaces: System.Runtime.CompilerServices.CallConvStdcall): (0x09000001).
    1>TestClass.obj : error LNK2022: metadata operation failed (8013118B) : Inconsistent implemented interfaces in duplicated types (types: cliext.impl.list_impl<int,0>; interfaces: System.IDisposable): (0x09000002).
    1>TestClass.obj : error LNK2022: metadata operation failed (8013118B) : Inconsistent implemented interfaces in duplicated types (types: cliext.impl.list_base<int,0>; interfaces: System.Runtime.CompilerServices.CallConvFastcall): (0x09000003).
    1>TestClass.obj : error LNK2022: metadata operation failed (8013118B) : Inconsistent implemented interfaces in duplicated types (types: cliext.impl.list_base<int,0>; interfaces: System.Runtime.CompilerServices.CallConvThiscall): (0x09000004).
    1>TestClass.obj : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (cliext._Dehandle<int>): (0x02000021).
    1>TestClass.obj : error LNK2022: metadata operation failed (8013118D) : Inconsistent layout information in duplicated types (cliext.is_handle<int>): (0x02000022).
    1>LINK : fatal error LNK1255: link failed because of metadata errors
    1>Build log was saved at "file://i:\dev\ians stuff\LNK2022\LNK2022\Debug\BuildLog.htm"
    1>LNK2022 - 11 error(s), 0 warning(s)
    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



    Friday, August 22, 2008 10:03 AM
  • I got the same issue with cliext::map<>. Thanks for the clue ian_lindsay! I have now moved the constructor to the header file (inline) and it compiles fine.

    Looks like a VC++ bug.

    Maciej
    Saturday, November 22, 2008 11:46 PM
  • Forgot to post what I finally ended up doing so others don't end up wasting as much time as I did.

    To stop the LNK2022 errors, the list template needs to be instantiated in the header to satisfy the generics stuff that goes on behind the scenes. To do this just write a function that uses the container in the header, e.g.:

    unsigned int stopLNK2022() { return m_list->size(); }

    Then  the rest of the real usage can be nicely encapsulated in the .cpp file as you would do with STL.

    Friday, December 19, 2008 11:20 AM
  •  Try explicit instantiation in the .cpp file by adding the following line after the includes.

    template class cliext::list<int>;

    I believe that should alleviate the need for fancy footwork and token junk code in the .h file.

    (NOTE: Still running VS2005 so can't verify. I've had to do this for my own template classes to eliminate similar errors.)

    Friday, December 19, 2008 11:38 PM
  • I had this same problem with cliext::deque<int>, so suspect it's generic with all container classes.

    Tried Rick Wheeler's solution in VC++ 2008 but it didn't solve the problem; ian_lindsay's junk function did the trick though, thanks!

    Friday, October 1, 2010 2:31 AM
  • That problem still exists in Visual Studio 2012 RC. In my case, I have the problem only when using /clr:safe option. That thread safe me the trouble of reinventing the wheel for functions like lower_bound that does not exist in BCL containers.

    It was working in some cases but not others and I was not able to figure out why before seeing that thread.

    Monday, July 23, 2012 5:28 PM