473,503 Members | 2,046 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

How to detect multiple lib versions?

Hi all,

I have authored several native DLLs (call them A, B, and C). These
libraries have references between each other (A calls B which calls C).
These libraries are built and made available to callers both in "debug" and
"release" versions. The release versions of the libraries are A, B, and C
(.lib and .dll), while the debug versions are A_debug, B_debug, and C_debug
(.lib and .dll).

Now, because these libraries maintain internal state and call into each
other, ugly things happen if a caller links with the release version of one
library and the debug version of another library. At run-time, this causes
both versions of some of the libraries to be simultaneously loaded. (For
example, if the user calls into the debug version of A, which calls into the
debug version of B, and then the user explicitly calls into the release
version of B, then both B and B_debug would be simultaneously loaded, each
with its own internal state.)

So, how can I detect when a program references the debug version of one of
my libraries and the release version of another library? Ideally, I'd like
to put some magic into the source code that causes a linker error.
Alternatively, I guess I could have DLL initialization code that somehow
detects when more than one instance of the DLL have been loaded.

TIA - Bob

Oct 8 '08 #1
13 1514
"Bob Altman" <rd*@nospam.nospamwrote in
news:ek**************@TK2MSFTNGP06.phx.gbl:
Hi all,

I have authored several native DLLs (call them A, B, and C). These
libraries have references between each other (A calls B which calls
C). These libraries are built and made available to callers both in
"debug" and "release" versions. The release versions of the libraries
are A, B, and C (.lib and .dll), while the debug versions are A_debug,
B_debug, and C_debug (.lib and .dll).

Now, because these libraries maintain internal state and call into
each other, ugly things happen if a caller links with the release
version of one library and the debug version of another library. At
run-time, this causes both versions of some of the libraries to be
simultaneously loaded. (For example, if the user calls into the debug
version of A, which calls into the debug version of B, and then the
user explicitly calls into the release version of B, then both B and
B_debug would be simultaneously loaded, each with its own internal
state.)

So, how can I detect when a program references the debug version of
one of my libraries and the release version of another library?
Ideally, I'd like to put some magic into the source code that causes a
linker error. Alternatively, I guess I could have DLL initialization
code that somehow detects when more than one instance of the DLL have
been loaded.

TIA - Bob
Another way is to specifically pull in the required library yourself:

#ifdef _DEBUG
#pragma comment(lib, "xerces-lb_2D.lib")
#pragma comment(lib, "xalan-lb_1D.lib")
#else
#pragma comment(lib, "xerces-lb_2.lib")
#pragma comment(lib, "xalan-lb_1.lib")
#endif // _DEBUG

(Obviously, this code was making use of the xerces and xalan libraries)
All you need to do is make sure the path is set to find the .libs.

I've made use of other 3rdParty libraries that do the same thing -
usually in a header file. (Like RogueWave's Stingray)

Dave Connet
Oct 8 '08 #2
My original problem description is less than crystal clear. Let me take
another run at it...

I am struggling with a problem similar to what happens if an app links with
the "debug" version of the C runtime library but a library that the app
links with uses the "release" version of the C runtime library. In the case
of the C runtime library, you get a linker error (or maybe it's a warning)
if the main app and all of the libraries that it links with do not all agree
on the C runtime library version (release, debug, DLL, or local).

In my case, I have several native libraries that I'll call A, B, and C. A
calls into B and C, and B calls into C. When I build these libraries in the
"release" configuration, I create A.dll (and A.lib), B.dll, and C.dll.
Also, in the "release" configuration, A specifies B.lib and C.lib as
required input libraries, and B specifies C.lib as a required input library.

When I build these libraries in the "Debug" configuration, I create
A_debug.dll (and A_debug.lib), B_debug.dll, and C_debug.dll. Also, in the
"debug" configuration, A specifies B_debug.lib and C_debug.lib as required
inputs, and B specifies C_debug.lib as a required input. The upshot of all
of this is that I have two different sets of internally consistent
libraries, one compiled for release and one compiled for debug.

Now, the applications that call into these libraries *must* build entirely
with one set of the libraries or the other. That is, an application must
link with A.lib, B.lib, and C.lib *or* A_debug.lib, B_debug.lib, and
C_debug.lib, but *never* with A.lib and B_debug.lib.

So, I'm looking for a way to implement some sort of check to ensure that
code that calls these libraries follows this rule. I would prefer a
link-time check (similar to what happens when the main app and its libraries
don't agree on the C runtime library). But, if I can't do that, I'd settle
for a run-time check. At run-time, if the app calls A.lib then B.lib and
C.lib will be loaded (because A calls into B and C). If the app directly
calls into B_debug.lib then both B.lib and B_debug.lib will be loaded (as
will C.lib and C_debug.lib). I could presumably have some sort of code in
the DLL startup code for B and C that detect this condition.

Huh... I don't know if this is any clearer, but it's definitely longer.
Maybe more is better ;-)

TIA - Bob
Oct 8 '08 #3

"David Connet" <st***@agilityrecordbook.comwrote in message
news:pW****************@flpi146.ffdc.sbc.com...
"Bob Altman" <rd*@nospam.nospamwrote in
news:ek**************@TK2MSFTNGP06.phx.gbl:
>So, how can I detect when a program references the debug version of
one of my libraries and the release version of another library?

Another way is to specifically pull in the required library yourself:

#ifdef _DEBUG
#pragma comment(lib, "xerces-lb_2D.lib")
#pragma comment(lib, "xalan-lb_1D.lib")
#else
#pragma comment(lib, "xerces-lb_2.lib")
#pragma comment(lib, "xalan-lb_1.lib")
#endif // _DEBUG
Thanks Dave. Unfortunately, that doesn't really help my situation. (Take a
look at my second posting. Hopefully it's a little bit clearer than my
original posting.) If a caller explicitly links with the debug version of
one library and the release version of another library then things don't
work correctly. Adding more library references (albeit correct ones)
programmatically doesn't help things, since the linker may still wind up
linking with the incorrect library.
Oct 8 '08 #4
>So, how can I detect when a program references the debug version of one of
>my libraries and the release version of another library? Ideally, I'd like
to put some magic into the source code that causes a linker error.
Bob,

Is (re)naming the library interfaces differently between debug and
release builds a possibility (similar to how Windows defines Ansi &
Unicode APIs)?

Dave
Oct 8 '08 #5

"David Lowndes" <Da****@example.invalidwrote in message
news:sh********************************@4ax.com...
So, how can I detect when a program references the debug version of one
of
my libraries and the release version of another library? Ideally, I'd
like
to put some magic into the source code that causes a linker error.

Bob,

Is (re)naming the library interfaces differently between debug and
release builds a possibility (similar to how Windows defines Ansi &
Unicode APIs)?

Dave
Hmmm... That's an interesting thought... but, no, I don't think that solves
anything. Here's the problem I have: Suppose the app calls the Initialize
routine in B_debug.dll. That routine does some work and leaves some state
information behind in variables that are private to the dll. Then, the app
incorrectly calls a routine in A.dll (rather than A_debug.dll, which would
have been correct). That routine calls into B (not B_debug) and discovers
that the state variables are not initialized. This is because B and
B_debug are different libraries, each with its own set of state data.
Having two sets of entry point names doesn't change anything in this
example.

Bob
Oct 8 '08 #6
>Is (re)naming the library interfaces differently between debug and
>release builds a possibility (similar to how Windows defines Ansi &
Unicode APIs)?

Hmmm... That's an interesting thought... but, no, I don't think that solves
anything. Here's the problem I have: Suppose the app calls the Initialize
routine in B_debug.dll. That routine does some work and leaves some state
information behind in variables that are private to the dll. Then, the app
incorrectly calls a routine in A.dll (rather than A_debug.dll, which would
have been correct).
Bob,

How (if the functions are named differently between debug & release
libs) would the same code base call into the debug version of one
library and the release version of another - providing the source code
plays by a consistent naming convention/macros you'd use to do the
renaming?

While you can cater for anarchy you can't cater for absolute anarchy
:)

Dave
Oct 9 '08 #7
"Bob Altman" <rd*@nospam.nospamwrote in
news:uO**************@TK2MSFTNGP02.phx.gbl:
>
"David Connet" <st***@agilityrecordbook.comwrote in message
news:pW****************@flpi146.ffdc.sbc.com...
>"Bob Altman" <rd*@nospam.nospamwrote in
news:ek**************@TK2MSFTNGP06.phx.gbl:
>>So, how can I detect when a program references the debug version of
one of my libraries and the release version of another library?

Another way is to specifically pull in the required library yourself:

#ifdef _DEBUG
#pragma comment(lib, "xerces-lb_2D.lib")
#pragma comment(lib, "xalan-lb_1D.lib")
#else
#pragma comment(lib, "xerces-lb_2.lib")
#pragma comment(lib, "xalan-lb_1.lib")
#endif // _DEBUG

Thanks Dave. Unfortunately, that doesn't really help my situation.
(Take a look at my second posting. Hopefully it's a little bit
clearer than my original posting.) If a caller explicitly links with
the debug version of one library and the release version of another
library then things don't work correctly. Adding more library
references (albeit correct ones) programmatically doesn't help things,
since the linker may still wind up linking with the incorrect library.
I guess I view this as a developer problem. If you're explicitly linking
to debug and release versions, then all bets are off and you deserve to
crash (yes, it's possible - but you must know what you're doing and the
interface must be designed to support this)! There's only so much you can
do without going crazy trying to prevent stupidity. You can always
program to prevent cluelessness, but stupid people are too clever
(there's a really good quote about this, but I can't remember...)

Dave
Oct 9 '08 #8
There's only so much you can
do without going crazy trying to prevent stupidity. You can always
program to prevent cluelessness, but stupid people are too clever
(there's a really good quote about this, but I can't remember...)
Welcome to my world. I spent the better part of a day trying to figure out
why one of my libraries, when called by a coworker's app, seemed to be
broken. Turned out that he had mixed references to the debug and release
versions of the libraries. I got some small satisfaction from slapping him
upside the head when I figured out what was going on, but I'd rather teach
the computer to automagically slap him for me...

Oct 9 '08 #9
How (if the functions are named differently between debug & release
libs) would the same code base call into the debug version of one
library and the release version of another - providing the source code
plays by a consistent naming convention/macros you'd use to do the
renaming?

Yes, you are correct. If I could somehow make the names exported by my DLLs
include the postfix "_debug" or "_release" depending on whether I built the
library in the "debug" or "release" configuration, and if I provided macros
in my library's header files to perform a similar transformation based on
whether the caller is building in "debug" or "release", then, yes, the
linker will catch the mismatched library references. If the caller,
building in "debug" configuration, calls A_foo and B_bar (in libraries A and
B respectively), that would turn into actual calls to A_foo_debug and
B_bar_debug. If the caller screwed up and tried to link with the "release"
version of library B then B_bar_debug would not be resolved by the linker.

The downside of this scheme is that changing routine names in the library is
(obviously) a breaking change. I can avoid breaking production code by
appending "_debug" in the debug version of the libraries while keeping the
original routine names in the release version of the libraries.

I think this could work. Now, how do I conditionally append "_debug" to my
routine names?

Oct 9 '08 #10
>I think this could work. Now, how do I conditionally append "_debug" to my
>routine names?
I guess you could have something like this:

#ifdef _DEBUG
#define Fn1 Fn1_debug
#endif

extern void Fn1();

void Fn1()
{
printf( __FUNCTION__ );
}

Dave
Oct 9 '08 #11
Bob Altman wrote:
>There's only so much you can
do without going crazy trying to prevent stupidity. You can always
program to prevent cluelessness, but stupid people are too clever
(there's a really good quote about this, but I can't remember...)

Welcome to my world. I spent the better part of a day trying to
figure out why one of my libraries, when called by a coworker's app,
seemed to be broken. Turned out that he had mixed references to the
debug and release versions of the libraries. I got some small
satisfaction from slapping him upside the head when I figured out
what was going on, but I'd rather teach the computer to automagically
slap him for me...
It does. Problem is that the error message suggests a way to ignore
multiple definitions instead of fixing the problem.
Oct 9 '08 #12
#ifdef _DEBUG
#define Fn1 Fn1_debug
#endif

void Fn1()
{
}
Oh... I didn't realize that I could use a macro like that. That suggests a
way that I can reasonably easily convert all of my exported functions for
the debug build only. I can define a helper macro that evaluates to either
the desired function name or the desired function name plus "_debug", like
this:

In MyLibHelper.h

#ifdef _DEBUG
#define EXPORT(name) name##_debug
#else
#define EXPORT(name) name
#endif

Then I can modify my existing header file and implementation files like
this:

In MyLib.h

#include "MyLibHelper.h"

int EXPORT(MyFunc1)(int arg);
void EXPORT(MyFunc2)(void);
int EXPORT(MyFunc3)(const char* arg1, int arg2);

In the implementation (cpp) files, I would use the same syntax:

#include "MyLibHelper.h"

extern "C" MYLIB_API int EXPORT(MyFunc1)(int arg)
{
<implementation>
}

Thanks a million Dave!

Bob
Oct 10 '08 #13
Bob Altman wrote:
>#ifdef _DEBUG
#define Fn1 Fn1_debug
#endif

void Fn1()
{
}

Oh... I didn't realize that I could use a macro like that. That
suggests a way that I can reasonably easily convert all of my
exported functions for the debug build only. I can define a helper
macro that evaluates to either the desired function name or the
desired function name plus "_debug", like this:

In MyLibHelper.h

#ifdef _DEBUG
#define EXPORT(name) name##_debug
#else
#define EXPORT(name) name
#endif

Then I can modify my existing header file and implementation files
like this:

In MyLib.h

#include "MyLibHelper.h"

int EXPORT(MyFunc1)(int arg);
void EXPORT(MyFunc2)(void);
int EXPORT(MyFunc3)(const char* arg1, int arg2);

In the implementation (cpp) files, I would use the same syntax:

#include "MyLibHelper.h"

extern "C" MYLIB_API int EXPORT(MyFunc1)(int arg)
{
<implementation>
}
Trouble is, your users also have to use the same syntax to get the _debug
automatically added. Maybe go with the original idea of redefining the
names themselves. Or better yet, avoid macros (unscoped) and declare a
bunch of inline functions to get the same effect.
>
Thanks a million Dave!

Bob

Oct 13 '08 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
10046
by: Szar | last post by:
JS noob. I've seen plenty of browser detection scripts but they all seem to be slightly different and don't really fit my needs. I have various places where if the browser is IE I'd like to display...
23
6470
by: David McCulloch | last post by:
QUESTION-1: How can I detect if Norton Internet Security is blocking pop-ups? QUESTION-2a: How could I know if a particular JavaScript function has been declared? QUESTION-2b: How could I...
23
15548
by: Michel Bany | last post by:
I am trying to parse responseXML from an HTTP request. var doc = request.responseXML; var elements = doc.getElementsByTagName("*"); the last statement returns an empty collection when running from...
0
1541
by: Fernando Nasser | last post by:
Multiple database services and multiple versions on Red Hat Linux systems The way it works is that we require a specific service script for each database service (that is listening on each port)....
1
2823
by: oreng | last post by:
Hey all, I have some problems detecting whether the client's browser javascript is enabled at the server side. While Request.Browser.JavaScript only check if the browser enable java script (and...
10
2108
by: Rich Kucera | last post by:
Holding all versions at 5.0.4, Multiple stacks with multiple-version configurations inevitable Will have to wait to see what the impact of problems such as http://bugs.php.net/bug.php?id=33643 ...
37
3690
by: Allen Browne | last post by:
If you develop for others, you probably have multiple versions of Access installed so you can edit and create MDEs for clients in different versions. This works fine under Windows XP, even with...
1
7164
by: bg_ie | last post by:
Hi, I created a COM object using C# and I installed it with a batch that looks something like this - ECHO OFF PATH = C:\WINNT\Microsoft.NET\Framework\v2.0.50727 set target=C:\mydll.dll echo...
4
6446
by: raylopez99 | last post by:
Compound question: first, and this is not easy, if there's a way to detect multiple simultaneous key presses in C# let me know (in the below code, keys c and d being pressed simultaneously or...
0
7204
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
7091
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
7282
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
7342
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
6998
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7464
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
1
5018
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3162
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1516
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.