473,324 Members | 2,400 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,324 software developers and data experts.

STL and DLL linkage (VC71/ VS2003) - Warning C4251

I am writing a shared object (Dll in Windows) and I am making extensive
use of the STL.

I am getting lots of warnings like this:

ClassA.h(139): warning C4251: 'ClassA::indexarray' : class
'std::vector<_Ty>' needs to have dll-interface to be used by clients of
class 'ClassA'
with
[
_Ty=int
]
My questions are:
1). Is this a VC7 (2003) specific problem?
2). How do I get rid of these warinings (without using #pragma disable
and without having to modify the sources of the STL)?
3). Is this fixed in VC8 (2005)?

Mar 16 '06 #1
6 2345
Hello Bart,

This is C# group. Ask your question in ".VC*", "*win32*" groups

BS> I am writing a shared object (Dll in Windows) and I am making
BS> extensive use of the STL.
BS>
BS> I am getting lots of warnings like this:
BS>
BS> ClassA.h(139): warning C4251: 'ClassA::indexarray' : class
BS> 'std::vector<_Ty>' needs to have dll-interface to be used by clients
BS> of
BS> class 'ClassA'
BS> with
BS> [
BS> _Ty=int
BS> ]
BS> My questions are:
BS> 1). Is this a VC7 (2003) specific problem?
BS> 2). How do I get rid of these warinings (without using #pragma
BS> disable
BS> and without having to modify the sources of the STL)?
BS> 3). Is this fixed in VC8 (2005)?
---
WBR,
Michael Nemtsev :: blog: http://spaces.msn.com/laflour

"At times one remains faithful to a cause only because its opponents do not
cease to be insipid." (c) Friedrich Nietzsche
Mar 17 '06 #2
>I am writing a shared object (Dll in Windows) and I am making extensive use
of the STL.

I am getting lots of warnings like this:

ClassA.h(139): warning C4251: 'ClassA::indexarray' : class
'std::vector<_Ty>' needs to have dll-interface to be used by clients of
class 'ClassA'
with
[
_Ty=int
]
My questions are:
1). Is this a VC7 (2003) specific problem?
2). How do I get rid of these warinings (without using #pragma disable and
without having to modify the sources of the STL)?
3). Is this fixed in VC8 (2005)?


HI,

most of the time this warning is harmless and you can safely disable it.
Sometimes the warning is indicating a problem though.

There is a good in-depth explanation here:
http://www.unknownroad.com/rtfm/Visu...ningC4251.html

--
Kind regards,
Bruno van Dooren
br**********************@hotmail.com
Remove only "_nos_pam"
Mar 17 '06 #3
Bart Simpson wrote:
My questions are:
1). Is this a VC7 (2003) specific problem?
Warnings were designed to draw your attention to a possible problem.
Normally you want to export your classes, but in case of the STL you
simply can not. The STL is implemented purely in header files, and
therefore there is really not much code that requires exporting. You can
safely disregard the warning, but you must ensure that all your DLLs and
the EXE use the exact same compiler settings and the same STL
implementation, and also the dynamic version of the C runtime library
(due to the fact that when you use the static RTL, each DLL has its own
heap).

There are some compilers that don't report warning messages regarding
this, but VC++ does.
2). How do I get rid of these warinings (without using #pragma disable
and without having to modify the sources of the STL)?
This is one of those very few cases where you can't get rid of the
warnings without the #pragma. There are some macros on this site:
http://www.unknownroad.com/rtfm/Visu...ningC4251.html

But first, they don't work with any modern VC++ (7.1, 8.0). So I tried
to create my own version that worked (http://tweakbits.com/DllExport.h),
but I've run into problems. If two DLLs export the same STL container
(such as set<int>), I often get a conflict, which prevents linking. I
absolutely don't recommend that you try to export STL containers, like
using my DllExport.h. It's nothing else but a nasty hack. Just
disregarding those warning solves the problem -- because simply there is
no problem to be solved. If you really want to, you can try to export
vector<T>, but even then you'll keep getting warnings regarding
vector<T>::iterator, and vector<T>::allocator. Don't even attempt
exporting any other STL containers. In my experience, you'll just cause
more trouble trying to export STL classes than dealing with the warning.
3). Is this fixed in VC8 (2005)?


No, the warning is still there. The compiler doesn't know that it's
compiling STL, and if it was not STL, the warning would (could) be valid.

Tom
Mar 17 '06 #4
Tamas Demjen wrote :
This is one of those very few cases where you can't get rid of the
warnings without the #pragma. There are some macros on this site:
http://www.unknownroad.com/rtfm/Visu...ningC4251.html

But first, they don't work with any modern VC++ (7.1, 8.0). So I tried
to create my own version that worked (http://tweakbits.com/DllExport.h),
I also use this trick in _DEBUG only, because in release I don't use
dlls. I also recommend not to export STL classes, e.g. not to use STL
types in dll interfaces.
#define EXPORT_STL_VECTOR(declspec_, T_) \
template class declspec_ std::allocator<T_ >; \
template class declspec_ std::vector<T_ >;


I recently modified this macros not to explicitly instanciate the vector
if the declspec_ is not defined to __declspec( something ) because I ran
into troubles in some very special circumstances.
Since in my case I export the vector in _DEBUG only, it looks like:

#ifdef _DEBUG
#define EXPORT_STL_VECTOR(declspec_, T_) \
template class declspec_ std::allocator<T_ >; \
template class declspec_ std::vector<T_ >;
#else
#define EXPORT_STL_VECTOR(declspec_, T_)
#endif

Otherwise, with such a define:

#ifdef _DEBUG
....
#else
#define MYEXPORT /*empty*/
#endif

The EXPORT_STL_VECTOR( MYEXPORT, int ) would expand in Release in an
explicit specialisation:

template class std::allocator<int>;
template class std::vector<int>;

which is at least not very useful.
3). Is this fixed in VC8 (2005)?

No, the warning is still there. The compiler doesn't know that it's
compiling STL, and if it was not STL, the warning would (could) be valid.


I don't know how they can fix it. If you compile a dll which asks for a
std::string with VC++ 6 and use this same dll from your VC++ 8 app, you
will get a problem because each compiler uses its own std::string, and
VC++ 8 will call std::string::c_str() of its STL on a VC++ 6 std::string
instance...

Even with the same compiler it is a problem, because the dll and the exe
both use their own std::string specialisation. If they are compiled with
the same compiler, they use the same code, but this code is still
duplicated. In fact, you have 2 same std::string types in you process :
the dll one and the exe one. They can be the same, but they can also be
different. For example, if your dll compiles std::vector with
_SECURE_SCL defined, and your exe doesn't, your app may crash.
--
Aurélien Regat-Barrel
Mar 20 '06 #5
Aurelien Regat-Barrel wrote:
I also use this trick in _DEBUG only, because in release I don't use
dlls. I also recommend not to export STL classes, e.g. not to use STL
types in dll interfaces.


If the DLL is a plugin, I always make sure not to use STL in exported
functions. My plugin architecture is such that any C++ compiler can be
used to write plugins. I often use a pure C interface for plugins. I
also assume that the plugin uses a different memory allocator than the
main application. Handling that requires special attention, such as
passing an allocator function to the DLL, or the DLL has to expose a
cleanup function (create and free pairs).

But that's a major pain, and it requires wrappers. It's way too
time-consuming for everyday programming. I'm not going to stop using the
STL in my normal (non-plugin) modules. I'm not going to write my own
containers just because C++ is an inherently non-portable language
(binary portability is absolutely non-existant). It's mainly a fault of
the operating system for not providing transparent object-oriented DLL
architecture. .NET is supposed to fix that with mixed success.

When I modularize my application, I have a choice to use either LIB
files or DLLs. LIBs are not any better, because they still require that
you use the exact same compiler, same STL version, and same compiler
options. It's still easier to work with DLLs, because they're already
linked, and stable DLLs don't change. Also using DLLs it's possible to
fix a bug in an application without having to rebuild the entire
application. This increases long-term stability, as opposed to a full
rebuild, which would be needed with LIBs. It's a big advantage to me to
have dynamic modules, even if they can be tossed away when upgrading to
a new compiler. I know what I'm doing is not portable, and I can safely
disregard those warnings regarding not exporting STL classes.

It would be nice to be able to disable those warnings explicitly for
each line. Something that would tell the compiler that I acknowledged
that and I still want to do it, don't show that warning for that line
anymore. Disabling all warnings is not good, and leaving the warnings in
just makes everyone disregard all warnings after a while, because we get
overwhelmed. Right now the solution is to rebuild everything with full
warnings enabled once a month or so, but turn a lot of those warnings
off during everyday development. It's not an ideal situation.

Tom
Mar 20 '06 #6
Tamas Demjen a écrit :
Aurelien Regat-Barrel wrote:
I also use this trick in _DEBUG only, because in release I don't use
dlls. I also recommend not to export STL classes, e.g. not to use STL
types in dll interfaces.

If the DLL is a plugin, I always make sure not to use STL in exported
functions. My plugin architecture is such that any C++ compiler can be
used to write plugins. I often use a pure C interface for plugins. I
also assume that the plugin uses a different memory allocator than the
main application. Handling that requires special attention, such as
passing an allocator function to the DLL, or the DLL has to expose a
cleanup function (create and free pairs).

But that's a major pain, and it requires wrappers. It's way too
time-consuming for everyday programming. I'm not going to stop using the
STL in my normal (non-plugin) modules. I'm not going to write my own
containers just because C++ is an inherently non-portable language
(binary portability is absolutely non-existant). It's mainly a fault of
the operating system for not providing transparent object-oriented DLL
architecture. .NET is supposed to fix that with mixed success.


I don't understand why the OS is responsible of that, and how it could
help in solving it; .Net works with the same OS, and it solves it. But
it uses generics, which are instantiated at runtime. C++/CLI offers both
templates and generics... Hum... That's a good question : how does
C++/CLI deals with managed templates across different assemblies?

VC++ allows you to export a template instantiation, which is not a
common feature as far as I know. I my case, exporting std::vector and
boost::shared_ptr made the warning disappear.
When I modularize my application, I have a choice to use either LIB
files or DLLs. LIBs are not any better, because they still require that
you use the exact same compiler, same STL version, and same compiler
options. It's still easier to work with DLLs, because they're already
linked, and stable DLLs don't change. Also using DLLs it's possible to
fix a bug in an application without having to rebuild the entire
application. This increases long-term stability, as opposed to a full
rebuild, which would be needed with LIBs. It's a big advantage to me to
have dynamic modules, even if they can be tossed away when upgrading to
a new compiler. I know what I'm doing is not portable, and I can safely
disregard those warnings regarding not exporting STL classes.
When you fix a bug in a LIB, without touching to its interface, you only
need to relink your application, and not to perform a full rebuild. If
you use libraries (DLL/LIB) in order to modularize your application, in
my opinion, LIBS a better for redistribution because:

- you don't need to wonder about __declspec()
- they allow better optimisation from the compiler, smaller size (in
particular if each dll uses its own CRT, which is safer if you want
stability)
- they reduce the time needed to load your app (dynamic linking has a cost)
- your app is monolithic : less risks to loose a dll, better protection
against curious guys (crackers, competitors, ...), illegal reuse of your
dll etc...
- you don't expose internal structures : dlls interfaces can be very verbose
- you don't have to wonder about which version of each dll is installed

Even with a dll you must take care about the way you compile it, and how
you use it. In particular with memory. If each dll has its own CRT, you
must be very careful the way you alloc/free objets in your app. For
example, in my case, I had a crash when my app exited, because the dll
which gave me some (exported) shared_ptr was unloaded by Windows before
others dlls which then tried to free this ptrs...
It would be nice to be able to disable those warnings explicitly for
each line. Something that would tell the compiler that I acknowledged
that and I still want to do it, don't show that warning for that line
anymore. Disabling all warnings is not good, and leaving the warnings in
just makes everyone disregard all warnings after a while, because we get
overwhelmed. Right now the solution is to rebuild everything with full
warnings enabled once a month or so, but turn a lot of those warnings
off during everyday development. It's not an ideal situation.


You can put all the "safe code" in a separated unit and disable the
warning for this file only. It is an idea...

Regards

--
Aurélien Regat-Barrel
Mar 21 '06 #7

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

Similar topics

2
by: Nahappan SM | last post by:
I have a struct : #include <string> struct __declspec (dllexport) FILEPROPERTIES { std::wstring FileName; std::wstring Type; };
5
by: Robert A Riedel | last post by:
I have a class that is intended to be exported in a DLL that uses another class that is in a static library. All clients that use the DLL will also link with the same static library. In summary,...
1
by: Peter Steele | last post by:
I've created an unmanaged C++ DLL and when I compile it I get numerous errors of the form xyz.cpp(nnn): warning C4273: '<somefunction>' : inconsistent dll linkage I have other DLLs that have...
2
by: Siemel Naran | last post by:
I keep getting warning messages like these: ....\include\myfile.h(451) : warning C4251: 'MyClass::m_myvariable' : class 'CPtrArray' needs to have dll-interface to be used by clients of class...
0
by: Bart Simpson | last post by:
I am writing a shared object (Dll in Windows) and I am making extensive use of the STL. I am getting lots of warnings like this: ClassA.h(139): warning C4251: 'ClassA::indexarray' : class...
5
by: Bart Simpson | last post by:
I am writing a shared object (Dll in Windows) and I am making extensive use of the STL. I am getting lots of warnings like this: ClassA.h(139): warning C4251: 'ClassA::indexarray' : class...
13
by: Anonymous | last post by:
On MS site: http://msdn2.microsoft.com/en-us/library/esew7y1w(VS.80).aspx is the following garbled rambling: "You can avoid exporting classes by defining a DLL that defines a class with...
6
by: =?Utf-8?B?RmFiaWFu?= | last post by:
Hello, I have a class hierarchy distributed over 3 native C++ dlls. The base class has a .NET Windows.Form for status output via a gcroot<>. The gcroot is declared private - the sub classes only...
6
by: The Architect | last post by:
Hi, If I have the same symbol in the .data section of 2 obj files, LD gives a multiple declaration error on linking? Would like to know the reason for this (diab only issues a warning) Also...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 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 former...

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.