Asked by:
Strange linker issues with STL/CLR
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.
MaciejSaturday, 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