Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is strcat Thread Safe?

502 views
Skip to first unread message

Jim

unread,
Jul 12, 1999, 3:00:00 AM7/12/99
to
Hi all,

I have a class I've subclassed from TServerClientThread that doesn't seem to
run without raising an EAccessViolation when I use strcat to build the
strings I return to my client.

Can anyone tell me if strcat is known to be thread (un)safe? If it isn't
can someone recommend an alternative that still uses simple c style char
arrays?

thanks in advance,

Jim


Stefan Hoffmeister (TeamB)

unread,
Jul 12, 1999, 3:00:00 AM7/12/99
to
: "Jim" <j...@acurion.com> wrote:

Jim, as usual the administrative note first: please do not cross- or
multi-post; people are not really fond of this and it leads to all sorts
of inefficiencies and confusion - major problems, in other words.

The newsgroups guidelines (see http://www.borland.com/newsgroups/)
specifically mention this case; you might want to check them out.

I have set followup-to borland.public.cppbuilder.vcl (though the .language
group would be most appropriate)

>Can anyone tell me if strcat is known to be thread (un)safe?

Well, strcat, like EVERY other function or method is not thread-safe in a
way. It always works on a variable and if access to this variable is not
serialized - boom.

You will need to show us a bit of source code if you want more details.


Jim

unread,
Jul 13, 1999, 3:00:00 AM7/13/99
to
Thanks for the response Stefan.

The code is relatively straightforward... I've pretty much copied the
example from the C++ Builder help. The stuff below works, and describes in
general how I want my code to run. However, I need to be able to build up a
string based on conditions that are driven by what's read from the client
socket. I've tried the following:


1. Declaring the variables used in the strcat statement as char __thread so
as to keep them thread safe.
2. Declaring char *msgToClient
3. Using char msgToClient[50]
4. Using string literals in the strcat (strcat(msgToClient, "QUIT\n);
5. Using variables (strcat(msgToClient, QUIT);

No matter how I declare the variables, the thread crashes with
EAccessViolation whenever strcat is used. This can happen with one
connected client and one thread or 10 clients and 10 threads.

Is this enough information? Please ask me any questions.

void __fastcall TAceProxyMessageHandler::ClientExecute()
{

if ( !Terminated & ClientSocket->Connected )
{

TWinSocketStream *pStream = new TWinSocketStream(ClientSocket, 60000);

try
{
char endLine[1] = {'\n'};
char buffer[10];
memset(buffer, 0, sizeof(buffer));

try
{
if ( pStream->WaitForData(60000)) // wait 60 seconds for the
client
{

if (pStream->Read(buffer, sizeof(buffer)) == 0) //if we can't
read close
ClientSocket->Close();
else
{


// (this works but doesn't satisfy my requirements i.e. to
build the string dynamically)
char msgToClient[50];
memset(msgToClient, 0, sizeof(msgToClient));
strcpy(msgToClient, "Hello from the Server\nQUIT\n");
ClientSocket->SendBuf(msgToClient, strlen(msgToClient));

} // (pStream->Read(buffer, sizeof(buffer) == o)

}
else
{
// we didn't get any data so quit
ClientSocket->Close();
} // ( pStream->WaitForData(60000))

}
catch (Exception &E)
{
if (!E.ClassNameIs("EAbort"))
{
AnsiString *errMsg = new
AnsiString((AnsiString)E.ClassName());
// int button = Application->MessageBox(errMsg->c_str(),
"Message Box", MB_OKCANCEL + MB_DEFBUTTON1);

ClientSocket->Close();
delete errMsg;
}

// Synchronize(HandleThreadException()); // you must write
HandleThreadException
}
}
__finally
{
delete pStream;

}
} // while
}


Thanks very much for your help. Sorry about the cross post.

Jim


Stefan Hoffmeister (TeamB) wrote in message
<379066a6...@forums.inprise.com>...

Paul Machiaverna

unread,
Jul 13, 1999, 3:00:00 AM7/13/99
to
Jim:
While I agree with Stefan and would like to see a code example of how you
are using strcat, may I suggest that you try to use the Windows API
functions instead of the C/C++ library functions. The Windows API offers a
function called lstrcat which has the same prototype as strcat. I use it in
multithreaded applications with no problem. My assumption here is that at
least the Windows API is thread safe.

The C++ Builder installation CD does contain a very nice online Windows API
reference. Depending on what type of installation you chose (typical,
custom, etc.) you may already have the online help already available on your
machine. Just look at the BCB sub menu off of the Start menu. Look for "MS
Help". If it's not there, simply install it from the BCB installtion CD.

Paul

Jim wrote in message <7mdktm$ro...@forums.borland.com>...
>Hi all,

Jim

unread,
Jul 13, 1999, 3:00:00 AM7/13/99
to
Hi Paul,

Thanks very much for your suggestion. I included the winbase.h and used the
lstrcat function. It worked very well. Do you suggest changing all my
string manipulation calls over to the win32 analogs?

Thanks again,

Jim

Gregory Forrest

unread,
Jul 13, 1999, 3:00:00 AM7/13/99
to
Is the line below supposed to be && instead of & ?

Paul Machiaverna

unread,
Jul 13, 1999, 3:00:00 AM7/13/99
to
Jim:
That's what I have done and it certainly made a lot of anomalies disappear.
If there is something that you can't find in the Win32 API, check out the
Borland supplied functions. For example, an easy way to convert from an
integer to a string is the IntToStr function. Note that the Win32 API does
not offer any floating point functions. This is where the Borland libraries
are a big help.

Paul

Jim wrote in message <7mfhas$g...@forums.borland.com>...

Stefan Hoffmeister (TeamB)

unread,
Jul 13, 1999, 3:00:00 AM7/13/99
to
: "Jim" <j...@acurion.com> wrote:

>1. Declaring the variables used in the strcat statement as char __thread so
>as to keep them thread safe.

No, this won't work. __thread just declares a new variable for each
thread.

> if ( !Terminated & ClientSocket->Connected )

As Gregory mentioned - this should probably the logical "&&" instead of
the binary "&".

> // (this works but doesn't satisfy my requirements i.e. to
>build the string dynamically)

Jim, what is the *failing* code?


> AnsiString *errMsg = new
>AnsiString((AnsiString)E.ClassName());

There is no need for this convoluted code. Simply

AnsiString errMsg = E.ClassName();

--
Stefan Hoffmeister (TeamB) http://www.econos.de/
Please do apply judgement when sending email.

Alex Bakaev [TeamB]

unread,
Jul 13, 1999, 3:00:00 AM7/13/99
to
Paul, I'm afraid you are wrong. I doubt that the lstrcat is thread-safe.
The problem is with the code that calls these functions, not functions
themselves ( as they operate on stack variables, which is by definition
is thread safe ). A reason to use Win32 APIs instead of C RTL ones is
smaller code size ( at the cost of lost portability ).

Alex

Paul Machiaverna wrote:
[snip]

--
HotSend - portable documents technology
http://www.hotsend.com/
eFax - get your faxes via email - Free !
http://www.efax.com

Paul Machiaverna

unread,
Jul 14, 1999, 3:00:00 AM7/14/99
to
Alex:
I'm curious if "Thread Safe" is simply a relative term here. As I posted in
my last message, I was having all sorts of problems using the C/C++ library
string functions in a multithreaded program. When I switched to the Win32
API, the problems disappeared. However, I must also add that I've always
had a synchronization object wrapped around the access to the strings. I
have never assumed that lstrcat or any other string function would perform
the proper blocking or signalling necessary to make the calls synchronous
(thread safe).

Paul

Alex Bakaev [TeamB] wrote in message <378BAB0F...@jetsuite.com>...
>... I doubt that the lstrcat is thread-safe....
>Alex


0 new messages