Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C run-time library

2 views
Skip to first unread message

Ele

unread,
May 30, 2004, 1:25:56 PM5/30/04
to
Among the following choices of C run-time ibrary,

Single-Threaded (LIBC)
Multithreaded (LIBCMT)
Multithreaded DLL (MSVCRT)
Debug Single-Threaded (LIBCD)
Debug Multithreaded (LIBCMTD)
Debug Multithreaded DLL (MSVCRTD)

when building a static library that uses multithreading, which C run-time
library should be used for "Debug" and "Release"?

If an application uses the static library, which C run-time library to use
for it of "Debug" and "Release" configurations?

Thanks!


Doug Harrison [MVP]

unread,
May 30, 2004, 2:59:40 PM5/30/04
to
Ele wrote:

>Among the following choices of C run-time ibrary,
>
>Single-Threaded (LIBC)
>Multithreaded (LIBCMT)
>Multithreaded DLL (MSVCRT)
>Debug Single-Threaded (LIBCD)
>Debug Multithreaded (LIBCMTD)
>Debug Multithreaded DLL (MSVCRTD)
>
>when building a static library that uses multithreading, which C run-time
>library should be used for "Debug" and "Release"?

The same one the library client would like to use.

>If an application uses the static library, which C run-time library to use
>for it of "Debug" and "Release" configurations?

The same one the library author used.

<g>

Seriously, the library and its clients need to use the same CRT. It's common
to provide a comprehensive selection of libraries, which allows the client
to make the CRT decision. So for a static library named x, you might have:

xs.lib - x static release
xsd.lib - x static debug
xsmt.lib - x static MT release
xsmtd.lib - x static MT debug
xdmt.lib - x DLL MT release
xdmtd.lib - x DLL MT debug

Then in some header file all your library headers #include, you can use
#pragma comment(lib) under the guidance of macros like _DEBUG, _MT, and _DLL
to ease selection of the correct .lib for the end user.

Things are a little different when x is a DLL, but in brief, if you'd like
x.dll and its client application to act more or less like a statically
linked C++ program, you should link them both to the same CRT DLL, so they
share CRT state like the heap, file descriptors, errno, etc. If they link to
different CRTs, the EXE and DLL will each have their own private copies of
the CRT state, which is a problem if your DLL isn't a true black box which
doesn't expect to share any state with the EXE.

--
Doug Harrison
Microsoft MVP - Visual C++

Ele

unread,
May 30, 2004, 7:15:14 PM5/30/04
to
Doug Harrison [MVP] <d...@mvps.org> wrote in message
news:lrakb0h4qt2sdpinh...@4ax.com...
Thanks!
"in some header file"? Which header file should be used?

"use #pragma comment(lib) under the guidance of macros like _DEBUG, _MT, and
_DLL to ease selection of the correct .lib for the end user."

Could you show me some code about doing this?

Carl Daniel [VC++ MVP]

unread,
May 30, 2004, 10:24:09 PM5/30/04
to
Ele wrote:
> "use #pragma comment(lib) under the guidance of macros like _DEBUG,
> _MT, and _DLL to ease selection of the correct .lib for the end user."
> Could you show me some code about doing this?

#ifdef _MT
#ifdef _DLL
#ifdef _DEBUG
#pragma comment(lib,"xdmtd.lib")
#else
#pragma comment(lib,"xdmt.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib,"xsmtd.lib")
#else
#pragma comment(lib,"xsmt.lib")
#endif
#endif
#else
#ifdef _DEBUG
#pragma comment(lib,"xsd.lib")
#else
#pragma comment(lib,"xs.lib")
#endif
#endif

> "in some header file"? Which header file should be used?

Whichever is the "main" header file that a client of your library would
#include.

-cd


Jerry Coffin

unread,
May 31, 2004, 12:33:43 AM5/31/04
to
In article <evLAasmR...@TK2MSFTNGP09.phx.gbl>, Ele...@movie.com
says...

None -- the compiler has a switch (/Zl) intended specifically for
compiling object files that are going to go into a library (in fact,
I'm reasonably certain the "l" was originally an abbreviation for
"library").

This flag prevents a default library record from being compiled into
the object file. That leaves it to the headers and/or user to
specify the library that will be used, so you can pick the one that's
suitable for the application at hand.

--
Later,
Jerry.

The universe is a figment of its own imagination.

Doug Harrison [MVP]

unread,
May 31, 2004, 11:54:06 AM5/31/04
to
Jerry Coffin wrote:

In a word, NO, NO, NO. OK, so that was three words. :) It's hard to imagine
a significant body of code that could be compiled in a CRT-neutral way. The
only reason I can see to use /Zl is to save space in libraries, which these
days would appear to amount to an insignificant amount of space.

See my answer and Carl's follow-up example for the correct approach.

Jerry Coffin

unread,
May 31, 2004, 4:11:55 PM5/31/04
to
In article <rfkmb056i2m2c28ao...@4ax.com>, d...@mvps.org
says...

[ ... ]

> In a word, NO, NO, NO. OK, so that was three words. :) It's hard to imagine
> a significant body of code that could be compiled in a CRT-neutral way.

I find it sufficiently easy to imagine that I do it on a regular
basis.

> The only reason I can see to use /Zl is to save space in libraries,

If that's all you can see, you should learn to look more carefully.

> which these
> days would appear to amount to an insignificant amount of space.

If space saving was the primary concern, they might as well remove
the switch entirely. It's not.



> See my answer and Carl's follow-up example for the correct approach.

I already saw them. IMO, far from being "the correct approach" they
presented what is, at best, a mediocre fall-back for dealing with
code that's usually poorly designed.

Doug Harrison [MVP]

unread,
Jun 1, 2004, 12:25:40 PM6/1/04
to
Jerry Coffin wrote:

>In article <rfkmb056i2m2c28ao...@4ax.com>, d...@mvps.org
>says...
>
>[ ... ]
>
>> In a word, NO, NO, NO. OK, so that was three words. :) It's hard to imagine
>> a significant body of code that could be compiled in a CRT-neutral way.
>
>I find it sufficiently easy to imagine that I do it on a regular
>basis.
>
>> The only reason I can see to use /Zl is to save space in libraries,
>
>If that's all you can see, you should learn to look more carefully.
>
>> which these
>> days would appear to amount to an insignificant amount of space.
>
>If space saving was the primary concern, they might as well remove
>the switch entirely. It's not.

Programs and the static libraries they use should be compiled using the same
CRT option and linked to the indicated CRT. The code that is generated
differs for the compiler switches which specify the CRT, namely /ML, /MT,
and /MD and their debug variants. You might want to grep the VC headers
separately for _DLL and _MT to convince yourself of this; it should at least
give you an idea where the static libraries you write "on a regular basis"
may fall apart when used in ways you haven't considered.

If you can avoid using those parts of the CRT that vary with the _DLL and
_MT macros and thus achieve your "CRT-neutral static library", by all means,
knock yourself out. Just be certain to vet everything with a high powered
microscope with each compiler version and CRT flavor you use, because as a
-Zl fan, you're sacrificing a useful link-time antibugging feature, while
making promises that can be broken for you at any time. I could see using
-Zl if you're not using the CRT at all, but if that's the case, why are we
having this discussion?

>> See my answer and Carl's follow-up example for the correct approach.
>
>I already saw them. IMO, far from being "the correct approach" they
>presented what is, at best, a mediocre fall-back for dealing with
>code that's usually poorly designed.

Then by that "reasoning", I guess MS is clueless with respect to lines
49-108 of afx.h. I guess MS and Dinkumware are out there in la la land with
yvals.h/use_ansi.h. And what about those "mediocre" Boost developers and
their auto_link.hpp. Are they all just a bunch of knuckleheads? Or is it
possible they understand the issues in greater depth than you and act
accordingly?

Jerry Coffin

unread,
Jun 1, 2004, 10:18:52 PM6/1/04
to
In article <8c9pb0hv625lgfl6s...@4ax.com>, d...@mvps.org
says...

[ ... ]

> Programs and the static libraries they use should be compiled using the same
> CRT option and linked to the indicated CRT. The code that is generated
> differs for the compiler switches which specify the CRT, namely /ML, /MT,
> and /MD and their debug variants.

/MD, /ML, etc., do NOT affect the compiler's code generation. These
flags define a couple of preprocessor macros and add a default
library record to the object file.

> You might want to grep the VC headers
> separately for _DLL and _MT to convince yourself of this; it should at least
> give you an idea where the static libraries you write "on a regular basis"
> may fall apart when used in ways you haven't considered.

Precisely what (mistaken) reasoning leads you to believe that they'll
have any affect on my code at all?



> If you can avoid using those parts of the CRT that vary with the _DLL and
> _MT macros and thus achieve your "CRT-neutral static library", by all means,
> knock yourself out.

Gee Doug, you're just too generous!

> Just be certain to vet everything with a high powered
> microscope with each compiler version and CRT flavor you use, because as a
> -Zl fan, you're sacrificing a useful link-time antibugging feature, while
> making promises that can be broken for you at any time.

No, Doug, I'm not doing anything of the sort. You're simply talking
about things of which you're completely ignorant.

> I could see using
> -Zl if you're not using the CRT at all, but if that's the case, why are we
> having this discussion?

Because you didn't bother attempting to learn any of the relevant
facts before you went on the attack.

> >I already saw them. IMO, far from being "the correct approach" they
> >presented what is, at best, a mediocre fall-back for dealing with
> >code that's usually poorly designed.
>
> Then by that "reasoning", I guess MS is clueless with respect to lines
> 49-108 of afx.h. I guess MS and Dinkumware are out there in la la land with
> yvals.h/use_ansi.h. And what about those "mediocre" Boost developers and
> their auto_link.hpp. Are they all just a bunch of knuckleheads? Or is it
> possible they understand the issues in greater depth than you and act
> accordingly?

Doug, you've apparently lost track of what the OP asked, or perhaps
you simply never understood it in the first place. In any case, none
of these is related or even analogous.

Here's the OP's question:

> when building a static library that uses multithreading, which C run-time
> library should be used for "Debug" and "Release"?

Now, I'll reiterate: there is really only one correct answer to this:
use /Zl, and allow the user to pick the correct CRT for his project.

When you build a static library, it's not linked to anything at that
point -- you simply create object files, and put them together into a
library.

It's up to the final user to decide which library he's going to link
with. When/if your library uses the CRT, it should make use of ONLY
its documented interface. Now it's true that the user's choices may
(often will) affect the _implementation_ of the standard library.

That's 100% IRrelevant to the question at hand though -- our library
has absolutely NO business depending on anything except the
documented behavior of the CRT. The CRT, in turn, is required to
provide that behavior, regardless of how it's implemented.

That leaves exactly three possible circumstances in which your
library has to care about which underlying CRT is used: 1) your
library depends on something it shouldn't, or 2) you're stuck with a
CRT that doesn't always live up to its requirements 3) some version
of the library simply doesn't include something you require (e.g. you
use _beginthread, so you need a multithreaded library).

In this case, he's already said that the library DOES use
multithreading, so we can preemptively rule out any possibility of
using the single-threaded libraries. That pretty much removes 3) as
a consideration. Between 1) and 2), the choice is pretty simple: at
least in my experience, the CRT is usually quite carefully written
and heavily tested, so it pretty dependably lives up the promises it
makes.

That leaves only one possibility: if your code cares which version of
the CRT it's linked with, it's depending on something that wasn't
promised to start with. I have no reservations in saying that most
such code is poorly designed (if anything, that's stating the
situation more weakly than it deserves).

Gil Hamilton

unread,
Jun 2, 2004, 7:57:25 AM6/2/04
to
Jerry Coffin <jco...@taeus.us> wrote in message news:<MPG.1b26e24a8...@msnews.microsoft.com>...

> > You might want to grep the VC headers


> > separately for _DLL and _MT to convince yourself of this; it should at least
> > give you an idea where the static libraries you write "on a regular basis"
> > may fall apart when used in ways you haven't considered.

> That's 100% IRrelevant to the question at hand though -- our library

> has absolutely NO business depending on anything except the
> documented behavior of the CRT. The CRT, in turn, is required to
> provide that behavior, regardless of how it's implemented.
>
> That leaves exactly three possible circumstances in which your
> library has to care about which underlying CRT is used: 1) your
> library depends on something it shouldn't, or 2) you're stuck with a
> CRT that doesn't always live up to its requirements 3) some version
> of the library simply doesn't include something you require (e.g. you
> use _beginthread, so you need a multithreaded library).

From a brief look at VC6 CRT source, I can only see a couple of
problem areas for going with your approach:

(1) errno - In _MT versions, errno (and _fpecode and a couple of
similar things) use TLS (thread local storage) to guarantee a unique
per-thread value.

(2) stdio macros (putchar, putc, etc.) - In _MT versions, these get
#undef'd in favor of a function version.

(3) C++ (iostream) objects. - Some of these (e.g. streambuf) have
different members based on _MT definitions.

It appears that, for (1) and (2), Microsoft's CRT implementation
arranges that one can compile one's library with _MT defined and
everything should work fine if it is then linked with either MT or
non-MT versions of the library. One's library objects then wouldn't
need to care which version they're being linked with (there is a
possible slight loss in stdio performance, but probably not
significant for most projects).

I'm not sure about (3). I think you'd be okay if you were careful
about exactly which classes you used (e.g. most programs don't use
streambuf directly and it isn't an actual base class of the more
commonly used iostream classes) but I'd want to look at it in more
depth before drawing any conclusions. In any case, though, that's C++
rather than C so it might not be necessary for many libraries anyway.

All in all, I'm (provisionally) a convert. I'll at least try the /Zl
approach next time I need to create a library like this.

- GH

Doug Harrison [MVP]

unread,
Jun 2, 2004, 1:21:42 PM6/2/04
to
Gil Hamilton wrote:

>From a brief look at VC6 CRT source, I can only see a couple of
>problem areas

<snip>

Kudos for going to the trouble to analyze this as suggested. However, note
that the VC6 CRT source you have is just a snapshot in time, and what I said
earlier concerning -Zl usage holds, namely, "Just be certain to vet


everything with a high powered microscope with each compiler version and CRT
flavor you use, because as a -Zl fan, you're sacrificing a useful link-time
antibugging feature, while making promises that can be broken for you at any
time."

>All in all, I'm (provisionally) a convert. I'll at least try the /Zl


>approach next time I need to create a library like this.

You'll still need to create release/debug versions of your libraries, and
your library clients will need to ensure they link to the correct one. In
addition, if you compile your library with /MT, your /MD users will call the
many __declspec(dllexport) functions in the CRT slightly less efficiently.
Finally, as already mentioned, MS doesn't find this approach suitable for
MFC or the C++ Standard Library. I think to consider this idea for libraries
that use the CRT is to borrow trouble, and I've got better things to do,
especially when the benefits conferred by /Zl are insignificant.

I'll leave you with these KB articles.

INFO: /Mx Compiler Options and the LIBC, LIBCMT, MSVCRT Libs
http://support.microsoft.com/?kbid=128641
<q>
All modules and static libraries within an application should use the same
compile options (/ML, /MT, or /MD) and link to the library cooresponding to
the selected option.
</q>

PRB: MFC and CRT Must Match in debug/release and static/dynamic
http://support.microsoft.com/?kbid=166504
<q>
If you are linking to any static libraries that also link to MFC or the CRT,
you should ensure that every static library shares the same properties
(debug/release, CRT-static/dynamic) as the application.
</q>

Gil Hamilton

unread,
Jun 3, 2004, 12:34:37 PM6/3/04
to
"Doug Harrison [MVP]" <d...@mvps.org> wrote in message news:<u23sb01gh5vr5tkkl...@4ax.com>...
> Gil Hamilton wrote:

> >All in all, I'm (provisionally) a convert. I'll at least try the /Zl
> >approach next time I need to create a library like this.
>
> You'll still need to create release/debug versions of your libraries, and
> your library clients will need to ensure they link to the correct one.

Is there a reason why would I need to provide separate release and
debug versions of my libraries.

> In
> addition, if you compile your library with /MT, your /MD users will call the
> many __declspec(dllexport) functions in the CRT slightly less efficiently.

I'd be interested in hearing about a scenario where this extra
instruction could be considered significant.

> Finally, as already mentioned, MS doesn't find this approach suitable for
> MFC or the C++ Standard Library. I think to consider this idea for libraries
> that use the CRT is to borrow trouble, and I've got better things to do,
> especially when the benefits conferred by /Zl are insignificant.

The hassle of maintaining (as library provider) and dealing with (as
library consumer) multiple versions of a library is a significant cost
to a project, one I'd love to jettison.

I don't know what the original motivation for having multiple versions
of the CRT was, but I can't imagine that, over the years, the benefits
have outweighed the hassles. I wonder whether, if they had it to do
over again, they'd make the same choice. (I note that, except for CRT
and MFC, Microsoft doesn't provide multiple versions of their own
libraries.)

> I'll leave you with these KB articles.

And I'll leave you with this interesting counterpoint from the CRT src
directory (in mterrno.c):

/***
*mterrno.c - provide function versions of errno & _doserrno for
*LIBC.LIB
[snip]
*Purpose:
* Sometimes users want to compile code (such as for use in
* a library) for both single-thread and multi-thread
* applications. Currently the one major stumbling block
* to doing this is the fact that errno & _doserrno are
* defined in different ways in LIBC.LIB and LIBCMT.LIB.
* Code that should otherwise be usable with both LIBC.LIB
* and LIBCMT.LIB but which accesses errno and/or _doserrno
* is not usable with both. By providing the function
* versions of errno & _doserrno in LIBC.LIB, users can
* compile their code for both LIBCMT.LIB and LIBC.LIB.
* Note that this does not magically make single-thread
* code safe in a multi-threaded environment, it merely
* makes it easier to use the same code with LIBC.LIB and
* LIBCMT.LIB.
*****************************************************************/

- GH

Doug Harrison [MVP]

unread,
Jun 3, 2004, 3:24:30 PM6/3/04
to
Gil Hamilton wrote:

>"Doug Harrison [MVP]" <d...@mvps.org> wrote in message news:<u23sb01gh5vr5tkkl...@4ax.com>...
>> Gil Hamilton wrote:
>
>> >All in all, I'm (provisionally) a convert. I'll at least try the /Zl
>> >approach next time I need to create a library like this.
>>
>> You'll still need to create release/debug versions of your libraries, and
>> your library clients will need to ensure they link to the correct one.
>
>Is there a reason why would I need to provide separate release and
>debug versions of my libraries.

Maybe you use assert? Maybe you write conditional code controlled by the
_DEBUG macro? Maybe you use special features of the debug heap, such as
#defining _CRTDBG_MAP_ALLOC and #including <crtdbg.h>? Maybe your users
would like to be able to step into your code without the debugger getting
confused by optimizations? That's just off the top of my head.

>> addition, if you compile your library with /MT, your /MD users will call the
>> many __declspec(dllexport) functions in the CRT slightly less efficiently.
>
>I'd be interested in hearing about a scenario where this extra
>instruction could be considered significant.

Sorry, I don't know of one offhand.

>> Finally, as already mentioned, MS doesn't find this approach suitable for
>> MFC or the C++ Standard Library. I think to consider this idea for libraries
>> that use the CRT is to borrow trouble, and I've got better things to do,
>> especially when the benefits conferred by /Zl are insignificant.
>
>The hassle of maintaining (as library provider) and dealing with (as
>library consumer) multiple versions of a library is a significant cost
>to a project, one I'd love to jettison.

Sure, but there are fundamental differences between compiling for debug and
release modes and ST and MT. I think it costs more to establish and maintain
for all time the "CRT-neutral static library" property, which the KB
articles I cited in my last message suggest isn't really supported, at least
not officially.

>I don't know what the original motivation for having multiple versions
>of the CRT was, but I can't imagine that, over the years, the benefits
>have outweighed the hassles.

Off the top of my head, all flavors of the MT CRT are very significantly
less efficient than the ST CRT with respect to simple I/O functions like
getc and even less simple ones such as those in the C++ streams library. I'm
hoping the next version will include non-locking versions of these functions
and expose the locking mechanism, so that one can write an efficient getc or
similar loop using the MT CRT. Then of course there are debug vs. release
versions of the CRT, which contain markedly different code, WRT both content
and optimizations.

Now that I'm thinking about it, I believe Whidbey does away with LIBC (the
ST CRT) and does expose the non-locking CRT functions, the latter something
I've been asking about for the last couple of releases.

>I wonder whether, if they had it to do
>over again, they'd make the same choice. (I note that, except for CRT
>and MFC, Microsoft doesn't provide multiple versions of their own
>libraries.)

Most MS libraries are packaged purely as DLLs, which don't integrate tightly
into the host application. However, the static library "commsup.lib" is
provided in release/debug, ANSI/Unicode variants, but otherwise appears to
be "CRT-neutral". There are some other smaller CRT-neutral .libs and .obj
files in the VC /lib directory. I think one could say that the smaller a
library is, the greater your ability to "prove" it's CRT-neutral and
maintain this property in the future, especially if you're MS, who can
define "CRT-neutral" for their own use without committing to a public
definition. If you find a public definition, please let me know!

>> I'll leave you with these KB articles.
>
>And I'll leave you with this interesting counterpoint from the CRT src
>directory (in mterrno.c):
>
>/***
>*mterrno.c - provide function versions of errno & _doserrno for
>*LIBC.LIB
>[snip]
>*Purpose:
>* Sometimes users want to compile code (such as for use in
>* a library) for both single-thread and multi-thread
>* applications. Currently the one major stumbling block
>* to doing this is the fact that errno & _doserrno are
>* defined in different ways in LIBC.LIB and LIBCMT.LIB.
>* Code that should otherwise be usable with both LIBC.LIB
>* and LIBCMT.LIB but which accesses errno and/or _doserrno
>* is not usable with both. By providing the function
>* versions of errno & _doserrno in LIBC.LIB, users can
>* compile their code for both LIBCMT.LIB and LIBC.LIB.
>* Note that this does not magically make single-thread
>* code safe in a multi-threaded environment, it merely
>* makes it easier to use the same code with LIBC.LIB and
>* LIBCMT.LIB.
>*****************************************************************/

That would be a lot more interesting if there were an article somewhere that
described all the "minor stumbling blocks" and other lacunae that no doubt
exist. It would also describe the valid combinations of /M[LTD]d? options
for the .obj files linked into an application. In the absence of such an
article, I'll continue to spend a few minutes per library setting up the
CRT-specific static libraries as described by myself and Carl, and remain
blissfully ignorant of these issues.

Jerry Coffin

unread,
Jun 3, 2004, 11:02:13 PM6/3/04
to
In article <df28a668.04060...@posting.google.com>,
gil_ha...@hotmail.com says...

[ ... ]

> Is there a reason why would I need to provide separate release and
> debug versions of my libraries.

A debug version _can_ be a bit easier for the user when he's doing
debugging, though in the end it's not really a necessity.

[ ... ]

> I don't know what the original motivation for having multiple versions
> of the CRT was, but I can't imagine that, over the years, the benefits
> have outweighed the hassles.

The single/multithreaded libraries go all the way back to OS/2 1.0.
At that time, savings was significant, but I'd agree that any more
that's much more questionable.

> I wonder whether, if they had it to do
> over again, they'd make the same choice. (I note that, except for CRT
> and MFC, Microsoft doesn't provide multiple versions of their own
> libraries.)

IMO, the only part that's open to question is whether they'd continue
this long -- at the time of OS/2 1.0, the had little choice.

0 new messages