LNK2005 from a C++/CLI dll linking against a non-CLR C++ static library

Hello all-

I have some static C++ libraries that I wrote in VS2003 but which upgraded fine when i went to VS2005 Pro. In them i overload the global versions of operators new, new[], delete, and delete[]. I also use the STL and parts of boost (shared_ptr<> and weak_ptr<>) pretty heavily. They have dependencies on various windows libs (dbghelp, winsock, etc...).

These static libraries have no common runtime support at all and use the Multi-Byte character set.

I'm trying to expose the functionality provided by my libs up to .NET by way of a C++/CLI DLL that links against them and exposes a new public ref class in the generated assembly. This new CLR class will wrap and broker their functionality to various C# apps.

I'm running into nasty linker errors, so I wrote a tiny little test case that reproduces the failures I'm getting. I'd really appreciate it if anyone would mind taking the time to look over them. The smallest way I could repro it was to create a VS2005 solution with 2 projects. The first is a C++ static library containing the dummy implementation and the second is a C++/CLR executable that uses the static library. Note that the problem occurs even if the C++/CLR project is a DLL; it doesn't seem related in any obvious way.

The non-CLR static library is contained in UnmanagedTest.h and UnmanagedTest.cpp as follows.

Unmanaged.h:
-----------------------------------------------------
#pragma once
#include <vector>

class Test
{
public:
Test();
~Test();

int* x;
std::vector<int> y;
};
-----------------------------------------------------



Unmanaged.cpp:
-----------------------------------------------------
#include "UnmanagedTest.h"
#include <cstdlib>

void* operator new(size_t size)
{
return std::malloc(size);
}

void operator delete(void* mem)
{
std::free(mem);
}

Test::Test()
{
x = new int[32];
for (int i = 0; i < 32; ++i)
x[ i] = i;
}

Test::~Test()
{
delete[] x;
}
-----------------------------------------------------

The .NET C++/CLI executable has the default AssemblyInfo.cpp and one .cpp file.

CppCliTest.cpp:
-----------------------------------------------------
#pragma unmanaged
#include "UnmanagedCppLib/UnmanagedTest.h"
#pragma managed

using namespace System;

int main()
{
Test* test = new Test;

for (int i = 0; i < 32; ++i)
Console::WriteLine(test->x[ i]);

delete test;

return 0;
}
-----------------------------------------------------

The linker errors i'm getting are as follows:

-----------------------------------------------------
UnmanagedCppLib.lib(UnmanagedTest.obj) : error LNK2005: "void __cdecl operator delete(void *)" ( 3@YAXPAX@Z) already defined in MSVCRT.lib(MSVCR80.dll)

D:\source\CppCliTest\Release\CppCliTest.exe : fatal error LNK1169: one or more multiply defined symbols found
-----------------------------------------------------

My UnmanagedCppLib is set to use the Debug Multithreaded DLL CRT in debug config and the Multithreaded DLL CRT in release. Interestingly, this all compiles cleanly, links cleanly, and runs as expected in Debug configuration. These link errors are only in Release build.

Here's where it gets a little crazy- I've found two separate ways to make this work in Release configuration:

1. remove the overloads of global operators new and delete from UnmanagedTest.cpp.

2. remove all references to std::vector from UnmanagedTest.h and UnmanagedTest.cpp

Making either of these changes gets rid of the link errors.

I figure I must be doing something wrong here, but after paring it down this far I can't figure out what to try next. Any time i see MSVCRT.lib conflicts I immediately think that i'm using the wrong version of the CRT but i only have one static lib (it uses MT DLL) and one C++/CLI DLL (it has no choice but to use MT DLL).

Any advice or suggestions would be greatly appreciated.

Thanks in advance,
Charles Nicholson


Answer this question

LNK2005 from a C++/CLI dll linking against a non-CLR C++ static library

  • jlgrau

    Yeah, I saw that post but it looks like it deals solely with bugs in the implementations of calloc and realloc. I'm only getting operator delete(void*) errors currently...
  • Hugo Salazar

    I'm wondering if this is related to the linking problem that affects VCMAME, Quake and projects that run SmartHeap:

    http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=133141&SiteID=1&PageID=0



  • Bhaskara.NET

    Turns out that if you disable WPO/LTCG in release build, everything works fine. I've submitted a bug report to labs.msdn.microsoft.com/productfeedback so hopefully they'll acknowledge it.


    Thanks to those who helped,
    charles

  • kiewie

    I should note that the link error also goes away if i set the non-CLR static lib to compile with CLR Support. I'd rather not go to the trouble of introducing a CLR configuration for these static libs, though. It seems like one main point of C++/CLI is the ability to bridge functionality from non-CLR libs to .NET...

    Anyway, I've scrubbed and uploaded my little repro case as a VS2005 .sln with 2 .vcprojs and source.

    I've put it online at http://cnicholson.net/CppCliTest.zip if anyone's feeling brave and/or couldn't be bothered to assemble a repro from my original cut-n-paste post :)

    TIA for any suggestions, corrections, advice, etc...

    Regards,

    Charles Nicholson


  • LNK2005 from a C++/CLI dll linking against a non-CLR C++ static library