Is there any good way to traversal a STL container cross dll boundary?

Jul 11, 2010 at 11:32am
For using the STL container corss dll is unsafety, I usually encapsulate the container after the interface. The normal way is like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Foo
{
public:
    /// m_iterator = m_myList.begin().
    void reset_first();
    /// check the end and set v = *m_iterator++
    bool get_next(int& v);
private:
    typedef std::list<int> IntList;
    IntList m_myList;
    IntList::iterator m_iterator;
};

Foo foo;
foo.reset_first();
int value;
while(foo.get_next(value))
{
    // ...
}


But I met a question when I actually use this kind of interface, it only suit for the single pass traversal. But it can not deal with two or more pass traversal, like this:
1
2
3
4
5
6
7
for(IntList::iterator i = m_myList.begin(), e1 = m_myList.end(); i != e1; ++i)
{
    for(IntList::iterator j = m_myList.begin(), e2 = m_myList.end(); j != e2; ++j)
    {
        // ....
    }
}


It is because I keep only one iterator inside my class. Is there any good way to resolve this, or some way and deal with STL container directly and saftity.
Jul 12, 2010 at 2:40am
Why is it not safe to expose an STL container from a DLL?
Jul 12, 2010 at 6:33am
For some of the STL implement like microsoft visual studio, they use static variable in the template. So there will two copy of the static variable in different DLL, and their value can not sync.
The MS said it should export the STL template instance, but I am not sure whether this problem will occur on other compiler or platform. And I see many expert always warning me not to pass a STL container cross DLL.
Jul 12, 2010 at 7:14am
You can use pointers to STL containers. It's safe in any case.
Jul 12, 2010 at 7:28am
Even pointer of reference is not safe.
It because dll is always need link, and the code will generate twice in two different dll.
The first thing is hard to make sure the two copy of code is all the same, for there have different macro and code generate options in two dll.
Even all the macros and compile options is the same, there still have the problem about static variable. If the template use a static variable, this variable will copy twice in two dll. Althrouth I get a pointer of a STL object, but the code to run it is inside this DLL.
For example if a template class has a static variable a for counting the instance number of the class. If cross the dll, the counter will have two copy, and the counting value is not accurate.

I am not sure whether I am understand this problem well, or is there have any way to resolve this?
Thank you.
Jul 12, 2010 at 8:13am
It all depends on what you're trying to access.

There is the problem of statics, but you shouldn't be accessing a DLL's static from outside the DLL anyway, so in practice, it's not a problem.

If you have macros that are exposing different interfaces to the DLL in different circumstances in the same program, you deserve what you get.

As for the main question of traversing an STL container, how is this container declared, and how are you accessing it (workaround aside)?

You may have already seen this.
http://msdn.microsoft.com/en-us/library/twa2aw10.aspx

If you take the view that C++ DLLs implement libraries with classes/functions as the only interface (not exported data), you'll never have a problem and using a WIN32 DLL will be as safe and equivalent to using a POSIX shared library.
Last edited on Jul 12, 2010 at 8:14am
Jul 12, 2010 at 8:34am
In fact what I want to ask is whether the custom dll can keep the iterator of a STL container in the producer dll, it a normal way to deal with multi-pass traversal.
I am afraid of the static variable because it hide behind the interfaces and I can not make sure the operation will not use the static variable, for there have kinds of implement of STL.
And kbw, I am not sure about the mean of "only interface", is there any example or something? Thank you.
Jul 12, 2010 at 8:55am
Is the container static? If so, why doesn't it have a context?

By interface, I mean means of using the DLL.

I'm really trying to find out what's in your DLL and how are you accessing it. I'm trying to understand if you have a static container and want to expose an interator on that.

In my view, a reasonably thought out interface doesn't have such constructs. You'd expect to see classes and possbly creator functions, but certainly no direct access to data.
Last edited on Jul 12, 2010 at 9:01am
Jul 12, 2010 at 9:14am
What I mean is not a static STL container. Think a simple template class like this:
template<typename T>
class Test
{
public:
Test()
{
++ms_instanceCounter;
}

~Test()
{
--ms_instanceCounter;
}

static std::size_t get_instance_count()
{
return ms_instanceCounter;
}
private:
static std::size_t ms_instanceCounter;
};

template<typename T>
std::size_t Test<T>::ms_instanceCounter = 0;

In the A.dll, I use it like this:
Test<int>* get_test()
{
return new Test<int>;
}

And I export the function get_test, in B.dll I use it:
Test<int>* t = get_test();
assert(Test<int>::get_instance_count() == 1);

The assert may not pass because the static ms_instanceCounter will have two copy in both dll. And I call the function get_test, the ms_instanceCounter in A.dll increase, but the ms_instanceCounter in B.dll is still 0.

I can not make sure the STL implement do not fall into this way, but I know at least MS STL has this problem.
Jul 12, 2010 at 12:06pm
Ok, I'm glad I don't do Windows programming. I'll let the Windows experts handle this one.
Jul 12, 2010 at 12:26pm
I wonder the static variable problem when using the template will not happend under linux when using the shared object?
Or the STL implement in gcc compiler is not using any static variable.
Jul 12, 2010 at 12:31pm
I managed to reproduce this multiple static instance thing.

1. Create DLL A with a static variable.
2. Create a function AF in DLL A that returns the address of the static.
3. Create DLL B that uses DLL A.
4. Create a function BF in DLL B that returns the address of the static by calling AF.
5. In your program, dynamically load DLL A/AF and DLL B/BF and call them. The addresses returned are different.

The program must have no link time knowledge of DLL A or DLL B.

I have to say, I have never knowingly had a problem with this.
Jul 12, 2010 at 12:40pm
Well, this is the microsoft talking about this problem, and some solution. I just want to know whether the same problem will happend in other platform.
http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b172396
http://support.microsoft.com/default.aspx?scid=kb%3ben-us%3b168958
Jul 12, 2010 at 1:27pm
I would think that libstdc++ would provide single instantiations all of the statics if there are any. I'm not aware
of any, nor am I aware of any such problems with gcc, and I use both the STL and shared objects quite
extensively (passing containers back and forth).
Jul 12, 2010 at 2:07pm
And the most terrible thing is the microsoft said this:

Also note that some STL containers (map, set, queue, list, deque) cannot be exported. Please refer to the More Information section to follow for a detailed explanation.

So only vector can export, I think I am more and more hate MS.
Jul 12, 2010 at 3:17pm
I think you've conflated two distinct issues. You have to solve them seperately.
1. How to deal with exporting STL containers.
2. How to deal with globals/statics in DLL instances.
Jul 12, 2010 at 4:01pm
Well, At first I know that STL containers can not cross DLLs, and I want to find out a method to deal with multi-pass traversal a container with an interface encapsulated.
It seems most of the time I was explaining why the STL containers can not cross DLL.
Let's back to the major subject, is there any suggestion to encapsulate a STL container and provide the ability of multi-pass traversal.

Thank you.
Jul 13, 2010 at 4:23am
I know that STL containers can not cross DLLs

You may say that, but in all my years of writing C++ DLLs, I've never had this problem.
Jul 13, 2010 at 9:32am
Topic archived. No new replies allowed.