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
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.
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>...
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,
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
Paul
Jim wrote in message <7mfhas$g...@forums.borland.com>...
>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
Paul Machiaverna wrote:
[snip]
--
HotSend - portable documents technology
http://www.hotsend.com/
eFax - get your faxes via email - Free !
http://www.efax.com
Paul
Alex Bakaev [TeamB] wrote in message <378BAB0F...@jetsuite.com>...
>... I doubt that the lstrcat is thread-safe....
>Alex