Sign in to follow this  

STL and DLL

This topic is 3460 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey All, Right, I'm developing a DLL which has a class in it and the class uses the standard template library object <map>. The <map> object is used to store a list of objects. Now my compiler is giving me a warning like this:
Quote:
c:\source\testdll\TestObject.hpp(54) : warning C4251: 'm_arrList' : class 'std::map<int,class cObject *,struct std::less<int>,class std::allocator<class cObject *> >' needs to have dll-interface to be used by clients of class '
Should I be worried about this?, I really don't want to go any further with the development until I know that this isn't going to cause me problems further down the line. Thanks.

Share this post


Link to post
Share on other sites
Exposing STL objects over a DLL boundary is usually a pretty bad idea for various reasons (CRT versions between the EXE and DLL need to match exactly, the memory allocation heaps need to be the same, and some other issues). I'd recommend exposing an abstract class from the DLL instead (See my post Here for an example).

Share this post


Link to post
Share on other sites
One danger lies in when a client might try to free memory of the container or allocate new memory for it. With a static C/C++ runtime library, each DLL or EXE does its own heap management. That means, if you allocate memory in code compiled into DLL A, then try to free that memory inside code compiled into DLL B, the heap in DLL B will not know where that memory comes from and at best do nothing.

Another danger are offset mismatches. As Steve already indicated, if you use the DLL with another version of your compiler in the future (or even another compiler, if they ever get their name-mangling unified ;)), the STL might have changed. The DLL may expect an std::map<> to have a stack size of 20 bytes, but due to clever optimizations, your new compiler's has only 16 bytes. Put a class with as a stack variable somewhere or derive from it and all hell will break loose.


If you hide the STL classes from public view or alternatively, use a dynamic (DLL-based) C/C++ runtime library and limit your binaries to only be used with the exact same compiler they were created with, then there's no danger at all.

You can select the dynamic runtime in Visual C++ by going to Project Settings, C/C++, Code Generation, Runtime Library. Choose "Multithreaded DLL" for Release builds and "Multithreaded Debug DLL" for Debug builds.

To avoid the warning, export only your public methods, not the whole class:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

class Test {
public: MYDLL_API void Foo();
public: MYDLL_API void Bar(int baz);
private: std::map<int, std::string> quz;
};

Share this post


Link to post
Share on other sites
@Evil Steve: I see. I suppose then I'm just going to have to be a little careful when I use this technique though, since I can see that I won't be able to actually derive from the class "cObject" in the calling application. Sure I'll be able to create an instance of it on the global heap, but I won't be able to reuse the code for additional classes. It sucks, but I guess I'm stuck with it.

Many Thanks.

EDIT: Oh dear this appears to have introduced some other problem. Now I'm getting this
Quote:
HEAP[Test.exe]: Invalid Address specified to RtlValidateHeap( 00C40000, 00D61B00 )
For the record Cygon I tried your fix on just exporting the functions that the calling application uses, and that cleared up lots of unresolved function errors that I was getting, so thanks. Anyway I don't think that it is STL that is the problem (but I'm probably wrong) as I commented out all of the STL code that I was using and I still got the same problem. Any ideas?.

[Edited by - Punchin Deck on June 24, 2008 7:08:20 AM]

Share this post


Link to post
Share on other sites
That is the exact error message you'll see in Visual C++ when you use a static runtime, allocate memory in DLL A and free it in DLL B (either A or B can of course also be your game executable, same situation)

Tips:
- Switch to the dynamic runtime
- Make sure you're not handing out a char * in your library that the caller has to free (std::string solves this trouble nicely with std::allocator in most STL implementations)
- Use boost::shared_ptr<> wherever you use new. shared_ptr<> will store a pointer to the proper ::operator delete and call it, even when it releases its memory in a DLL other than the one it was created in)

Share this post


Link to post
Share on other sites

This topic is 3460 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this