DLL runtime and /CLR compiling

M

Markus Ewald

I'm just experimenting around with the VisualC++ 2005 Express Edition Beta
and found some strange behavior for which I can't seem to find a workaround.

What I've done is set up two static library projects for Lua 5.0.2 and
LuaBind beta-6, compiling both with no CLR support and configured to use the
Multithreaded DLL runtime. Then I created a new console application which
makes use of these two static libraries (of course, also set to MT DLL). So
far so good, everything works.

When I then turned on CLR support for this console application, the linker
complained about symbols from the runtime libraries being defined mutiple
times - eg. in msvcprtd.lib (DLL runtime) and *libcpmtd.lib* (static
runtime).
Where does that come from ?
I thought the CLR mode event requires MT DLL compilation ?

Some of the errors I'm getting:
MSVCRTD.lib(MSVCR80D.dll) : error LNK2005: "public: virtual __thiscall
std::exception::~exception(void)" (??1exception@std@@UAE@XZ) already defined
in vc8test.obj
MSVCRTD.lib(MSVCR80D.dll) : error LNK2005: "public: __thiscall
std::exception::exception(void)" (??0exception@std@@QAE@XZ) already defined
in vc8test.obj
MSVCRTD.lib(MSVCR80D.dll) : error LNK2005: "public: __thiscall
std::exception::exception(class std::exception const &)"
(??0exception@std@@QAE@ABV01@@Z) already defined in vc8test.obj
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall
std::_Container_base::~_Container_base(void)"
(??1_Container_base@std@@QAE@XZ) already defined in vc8test.obj
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall
std::_Lockit::~_Lockit(void)" (??1_Lockit@std@@QAE@XZ) already defined in
libcpmtd.lib(xlock.obj)
msvcprtd.lib(MSVCP80D.dll) : error LNK2005: "public: __thiscall
std::_Lockit::_Lockit(int)" (??0_Lockit@std@@QAE@H@Z) already defined in
libcpmtd.lib(xlock.obj)

If anyone can suggest a workaround or knows what might be causing
libcpmt(d).lib to be linked I'd be more than happy ;-)

-Markus-
 
M

Markus Ewald

I myself wrote in message
I'm just experimenting around with the VisualC++ 2005 Express Edition Beta
and found some strange behavior for which I can't seem to find a
workaround.

What I've done is set up two static library projects for Lua 5.0.2 and
LuaBind beta-6, compiling both with no CLR support and configured to use
the Multithreaded DLL runtime. Then I created a new console application
which makes use of these two static libraries (of course, also set to MT
DLL). So far so good, everything works.

When I then turned on CLR support for this console application, the linker
complained about symbols from the runtime libraries being defined mutiple
times - eg. in msvcprtd.lib (DLL runtime) and *libcpmtd.lib* (static
runtime).

I've tried around with some other libraries and observed, that those errors
appear whenever I link an unmanaged static library making use of the C++
runtime into a managed project. It doesn't happen with pure C projects.

So, in the context of my initial project, compiling LuaBind with the /CLR
option solves the problem. Strange.

-Markus-
 
M

Markus Ewald

Looks like that assumption was a bit premature. To crash my app, I need no
more than this:

1) Create a new windows forms based application
2) Change the CLR option from pure CLR to normal CLR linkage
3) #include <string> and write something like std::string test = "hello
world"; in Main()
-> dbgheap.c #1301 Assertion pUserData != 0
-> Ignore leads to Access Violation

Callstack at time of assertion is
msvcr80d.dll!_msize_dbg(void * pUserData=0x00000000, int nBlockUse=2)
Line 1301 + 0x26 bytes C++
msvcr80d.dll!_dllonexit_nolock(int (void)* func=0x004535e0, void (void)* *
* pbegin=0x0046a4f4, void (void)* * * pend=0x0046a4f0) Line 282 + 0xd bytes
C
msvcr80d.dll!__dllonexit(int (void)* func=0x004535e0, void (void)* * *
pbegin=0x0046a4f4, void (void)* * * pend=0x0046a4f0) Line 259 + 0x11 bytes
C
VC8Test.exe!_onexit(int (void)* func=0x004535e0) Line 83 + 0x2e bytes C
VC8Test.exe!atexit(void (void)* func=0x004535e0) Line 98 + 0x9 bytes C
VC8Test.exe!std::initlocks::`dynamic initializer'() Line 49 + 0x17 bytes
C++
VC8Test.exe!_initterm(void** pfbegin = 0x00469008, void pfend = ) Line 140
C++
VC8Test.exe!?.cctor@@$$FYMXXZ() Line 297 C++

-Markus-
 
M

Markus Ewald

Ok, last message now. The cause seems to be an atexit() call issued from
std::initlocks. Could well be that the C++ runtime doesn't work at all in
/CLR applications compiled by Visual C++ 2005 Express Beta 1. Too bad :-(

-Markus-
 
S

Sri Vasudevan [MSFT]

It looks like one of the static libs is still statically linking to the CRT
runtime. Ensure that all the components including your libs are compiled
with the /MD switch (or /MDd for debug mode).

Thx,
Sri Vasudevan [MSFT]
Visual C++ team
 
M

Markus Ewald

Sri Vasudevan said:
It looks like one of the static libs is still statically linking to the
CRT runtime. Ensure that all the components including your libs are
compiled with the /MD switch (or /MDd for debug mode).
They are. The project consists of a .NET application and a single static C
library, I've double checked that both are compiled with /MD for release and
/MDd for debug mode. If I link (and use) the produced libraries in a normal
Win32 application (no .NET) also set to use the DLL runtime, no warnings or
errors whatever occur.

I have tried to isolate the cause, and can reproduce the access violation I
got when linking to another /CLR compiled .dll with two almost unchanged
..NET projects:

* Created a new .NET class library and a .NET console application
* Moved both projects into the same folder
* Changed build configuration so 'debug' and 'release' folders don't collide
* Changed output folder so both .dll and .exe would be put in the same dir
* Added a reference from the console application to the class library
* Included <string> in the class library

What happens is that an atexit() call issued from std::initlocks causes an
access violation due to __onexitbegin (declared in
F:\beta1\vctools\crt_bld\self_x86\crt\src\atonexit.c #39) being a NULL
pointer. I have uploaded a demonstration project here:
http://cygon.lunaticsystems.com/msvc8_crt_crash.zip

I'm not sure whether I'm just doing something blatantly stupid (can't see
what) or whether this is an actual bug, because, if I do the same without
moving the project's source files into seperate folders, it seems to work
fine.
Thx,
Sri Vasudevan [MSFT]
Visual C++ team
-Markus-
 
S

Sri Vasudevan [MSFT]

I was referring to the linker errors you were mentioned.

The access violation you are seeing has now been fixed and will be available
in the next release.

Thx,
Sri Vasudevan [MSFT]
Visual C++ team


--
This posting is provided "AS IS" with no warranties, and confers no
rights."Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm"
Markus Ewald said:
Sri Vasudevan said:
It looks like one of the static libs is still statically linking to the
CRT runtime. Ensure that all the components including your libs are
compiled with the /MD switch (or /MDd for debug mode).
They are. The project consists of a .NET application and a single static C
library, I've double checked that both are compiled with /MD for release
and /MDd for debug mode. If I link (and use) the produced libraries in a
normal Win32 application (no .NET) also set to use the DLL runtime, no
warnings or errors whatever occur.

I have tried to isolate the cause, and can reproduce the access violation
I got when linking to another /CLR compiled .dll with two almost unchanged
.NET projects:

* Created a new .NET class library and a .NET console application
* Moved both projects into the same folder
* Changed build configuration so 'debug' and 'release' folders don't
collide
* Changed output folder so both .dll and .exe would be put in the same dir
* Added a reference from the console application to the class library
* Included <string> in the class library

What happens is that an atexit() call issued from std::initlocks causes an
access violation due to __onexitbegin (declared in
F:\beta1\vctools\crt_bld\self_x86\crt\src\atonexit.c #39) being a NULL
pointer. I have uploaded a demonstration project here:
http://cygon.lunaticsystems.com/msvc8_crt_crash.zip

I'm not sure whether I'm just doing something blatantly stupid (can't see
what) or whether this is an actual bug, because, if I do the same without
moving the project's source files into seperate folders, it seems to work
fine.
Thx,
Sri Vasudevan [MSFT]
Visual C++ team
-Markus-
 
A

Arnaud Debaene

Sri said:
It looks like one of the static libs is still statically linking to
the CRT runtime. Ensure that all the components including your libs
are compiled with the /MD switch (or /MDd for debug mode).

I have also observed this behaviour with modules correctly linked to the CRT
DLL. If you want, I can send you a repro-case.

Arnaud
MVP - VC
 
M

Markus Ewald

Sri Vasudevan said:
I was referring to the linker errors you were mentioned.
I got that, but am 'still trying to isolate the minimum steps required to
reproduce it ;)
The access violation you are seeing has now been fixed and will be
available in the next release.
That's great!
Thx,
Sri Vasudevan [MSFT]
Visual C++ team
-Markus-
 
A

adebaene

Sri said:
You can send a bug report with what you are seeing at
http://lab.msdn.microsoft.com/productfeedback/
Done :
http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx?feedbackId=FDBK21096

If you can repro it in a few lines of code, then you can also paste it here
and I will take a look.

Sure :
- Create an unmanaged lib and add a class to it :
//file A.h
#pragma once
#include <string>

class A
{
public:
A(void);
~A(void);

std::string f();
};

//file A.cpp
#include "StdAfx.h"
#include "a.h"

A::A(void)
{}

A::~A(void)
{}

std::string A::f()
{
return "toto";
}

Make sure to compile this library with /MD (or /MDd).


Next, Create a managed C++/CLI assembly (a Class Library).
Add a managed class to this assembly :
//class ManagedWrapper.h
#pragma once
#include "../UnmanagedLibrary/A.h"

using namespace System;

namespace ManagedWrapper
{
public ref class AWrapper
{
public:
AWrapper();
~AWrapper();
String^ f();
private:
::A* p_A;
};
}

//file ManagedWrapper.cpp
#include "stdafx.h"
#include "ManagedWrapper.h"

namespace ManagedWrapper
{
AWrapper::AWrapper()
{
p_A=new A();
}

AWrapper::~AWrapper()
{
delete p_A;
}

String^ AWrapper::f()
{
return gcnew String (p_A->f().c_str());
}
}

Make sure the assembly is compiled with /MD (or /MDd). This is the
default of course.


Add the unmanaged library to the references of the assembly. Try to
build. I get the following linker errors :
Linking...
2>libcpmt.lib(string.obj) : error LNK2005: "public: __thiscall
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >(char const *)"
(??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z)
already defined in msvcprt.lib(MSVCP80.dll)
2>libcpmt.lib(locale.obj) : error LNK2005: "public: __thiscall
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >(char const *)"
(??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z)
already defined in msvcprt.lib(MSVCP80.dll)
2>libcpmt.lib(locale0.obj) : error LNK2005: "public: __thiscall
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >(char const *)"
(??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z)
already defined in msvcprt.lib(MSVCP80.dll)
2>libcpmt.lib(wlocale.obj) : error LNK2005: "public: __thiscall
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >(char const *)"
(??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z)
already defined in msvcprt.lib(MSVCP80.dll)
2>libcpmt.lib(xlocale.obj) : error LNK2005: "public: __thiscall
std::basic_string<char,struct std::char_traits<char>,class
std::allocator<char> >::basic_string<char,struct
std::char_traits<char>,class std::allocator<char> >(char const *)"
(??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@PBD@Z)
already defined in msvcprt.lib(MSVCP80.dll)
2>D:\users\adb\dev\temp\TestWhidbeyMixte\Release\ManagedWrapper.dll :
fatal error LNK1169: one or more multiply defined symbols found

Arnaud
MVP - VC
 
S

Sri Vasudevan [MSFT]

Thank you. This has already been fixed, and should be available in the next
release.

Thanks

--
Sri Vasudevan [MSFT]
Visual C++ Team

This posting is provided "AS IS" with no warranties, and confers no
rights."Use of included script samples are subject to the terms specified at
http://www.microsoft.com/info/cpyright.htm"
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top