copy a list in 1 instruction. Found problem.

copy a list in 1 instruction. Found problem.

Post by Jgen Devli » Sat, 07 May 2005 22:45:47


Hi,

For all those that suffered and will suffer the same experiences, here the
result.

We used the STL implementation delivered by Microsoft with Visual Studio 6,
which is actually an old Dinkumware implementation, in a multithreaded
environment. Well, it's very simpel. Don't.

Of course we were aware that the STL implementation was not thread-safe. So,
we protected all container actions using semaphores. Well, that's not
enough. The simpel fact that you use std::string from multiple threads will
cause your application to crash in the routines that do string manipulation
/ creation.

Here is a 20 lines example, that will crash within a second, although
nothing is wrong with the code:
#include <string>
#include <time.h>
#include <stdio.h>
#include <windows.h>

unsigned long __stdcall test(void *dummy_p)
{
for (;;)
{
std::string strTest;
for (int i=0;i<10;i++)
{
strTest += "abcdef";
}
}
return 0;
}

void main(void)
{ int i;

DWORD thread_id;

for (i=0;i<100;i++)
CreateThread(NULL,0,test,(void *)i,0,&thread_id);

char buffer[100];
gets(buffer);
}

As you see, only a local stack variable (the string strTest) is manipulated,
so one would think it should not be protected. Well, wrong about that.

Applying a fix available from Dinkumware doesn't help if you compile
"multithreaded dll", since the offending code is then in the dll.

The solution was to move to StlPort. It costed some days to move all our
code, but appart from 1 small issue that is not compatible (the iterator
change if you call delete on a std::set::iterator), we didn't have to change
our code.

Hope to help some people that face the same problem.

Jgen Devlieghere
 
 
 

copy a list in 1 instruction. Found problem.

Post by Igor Tande » Sat, 07 May 2005 22:59:41


Seems to work for me. Running VC6 SP5, set to link against Multithreaded
DLL CRT.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925

 
 
 

copy a list in 1 instruction. Found problem.

Post by Tom Widme » Sun, 08 May 2005 00:18:33


>

Only if you copy the string from another thread. The COW sematics don't
work in a multithreaded environment, you you have to make sure you
unshare the string in a synchronized code block. e.g.

lock
string s = t;
//s and t share representation.
s.begin(); //unshare
unlock
//now s is fully independent.


It doesn't crash for me. Are you using a multithreaded CRT?


Indeed, and it doesn't crash.


True, but the fix only saves you from having to do the workaround I
mention above. I think set and map can cause problems if you don't get
the fixes from the dinkumware site, but fortunately they aren't in the
dll, so the fixes do actually work.


If you erase a set iterator, that iterator is invalidated! It sounds
like your code had undefined behaviour...

Tom
 
 
 

copy a list in 1 instruction. Found problem.

Post by Marc Sherm » Sun, 08 May 2005 02:44:41


Does this work because string had better make a private copy before
returning a non-const iterator?

Would the following also work?

string s = t.c_str();

thanks,
Marc
 
 
 

copy a list in 1 instruction. Found problem.

Post by Tom Widme » Tue, 10 May 2005 19:24:23


Yes.


Yes, though the semantics are different if t is a string containing
embedded '\0' characters.
string s(t.data(), t.size());
fixes that problem, and it probably a better solution than the one I
originally posted.

Tom