Puzzling segmentation fault on FD_ISSET()

A

Alvin

Note: Source code and compile commands are at the bottom.

I've spent some time with a friend making a nice and simple to use
OOPified C++ networking layer for TCP that works on multiple
platforms. As I was about to conclude its functionality and simply
testing it on win32, I ran into a strange problem (I'll cover it in a
moment). Everything compiles cleanly (-Wall barfs lots of warnings,
but they just complain about type casting) on all platforms, but the
same error happens on all platforms, too. And not on just one computer
or locally, either.

Anyway, the error is put simply, a segmentation fault. When my example
multiplexing server runs along side the complimentary client example,
everything is fine until excessive connections commence. A few more
clients don't harm it at all, but add more than 3 and - depending on
seemingly nothing - as soon as one last client joins, it will give in,
segfault and attempt to send a FIN to every connection (but apparently
fails to contact all clients all the time, if ever - my observations
weren't geared to this specific aspect). There's no specific limit,
but it seems to never be less than 4 connections.

To be more specific, as soon as the last client ("last straw on the
camel's back") connects, the server will segfault. After a few tries
on various machines, remote connections, different operating systems
and such, it seemed that it wasn't a one-off thing or platform
specific. I ran it through GDB:

Program received signal SIGSEGV, Segmentation fault.
Error while running hook_stop:
Invalid type combination in ordering comparison.
0x0804997c in Select::StartSelect (this=0xbfb5aa10) at dhsocks.cpp:
433
433 if(FD_ISSET(readsock->GetSocket(), &readfd)) {

It puzzles me as to why it fails on the condition above. The fact that
it doesn't generally have a set limit and is seemingly random (but
never very high).

Anyway, that's as far as I've investigated and I can't see anything
even remotely useful (the debug message is rather ambiguous - as I
said, I can't imagine why it would segfault there). By far the
strangest error I've ever encountered.

I'm hoping the collective knowledge of people who look here can help
solve the problem. I've never really seen anything like this before,
so I'm stuck. I've no idea what to Google either.

Thanks,
Alvin.

(it's called dhsocks if that helps to understand anything)

Source code:
HTTP: http://svn.digital-haze.net/dl.php?repname=dhsocks&path=
%2F&rev=39&isdir=1 (tarball)
SVN: svn co -r 39 http://svn.digital-haze.net/dhsocks (will make
dhsocks directory in working directory)

Compile commands:
g++ ./dhsocks.cpp ./selectserv.cpp -o ./selectserv -ggdb
g++ ./dhsocks.cpp ./selectclient.cpp -o ./selectclient -ggdb
 
T

Thomas J. Gritzan

Alvin said:
I've spent some time with a friend making a nice and simple to use
OOPified C++ networking layer for TCP that works on multiple
platforms.
[...]

A very good example of very bad C++. Sorry.

Some points:

(Source code is here:
http://svn.digital-haze.net/dl.php?repname=dhsocks&path=
%2F&rev=39&isdir=1 (tarball))

1) int Socket::Send(char *str, int length)
{
[...]
char sendstr[length];

Lengths of arrays must be compile time constants in C++. This doesn't
compile unless you use a gcc extension.

2) In main():

temp->Send(asdf, sizeof(packet));

You try to send sizeof(packet) data but you don't know how big the buffer
asdf pointing to is.

3) You leak memory. Socket::Recv retuns a buffer new'ed in the function
that never gets released.

4) You mix value semantics and reference semantics (pointers):

Socket Socket::Accept();
Socket* Select::StartSelect();

5) No exception safety. The are no destructors that close sockets. Google
for "RAII".
Program received signal SIGSEGV, Segmentation fault.
Error while running hook_stop:
Invalid type combination in ordering comparison.
0x0804997c in Select::StartSelect (this=0xbfb5aa10) at dhsocks.cpp:
433
433 if(FD_ISSET(readsock->GetSocket(), &readfd)) {


I think the problem is elsewhere. But the socket functions you use are
offtopic here. Better ask in a platform specific newsgroup, but one I found:

<OT>
In char *Socket::Recv():

int size;
int n = recv(sockfd, (char *) &size, sizeof(int), MSG_PEEK);

recv() doesn't fill the data size in the second parameter, it puts the data
into the size variable. So whatever data you get, you work with some
undefined size and use it to allocate the buffer.

You gt undefined behaviour and your program crashes.
</OT>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top