Problem catching exception

Mar 6, 2012 at 3:29am
Hi everyone, i have the following code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

string server::recibirBuffer()
{
    string rtn;
    char buffer[MAX_BUFFER+1];
    DWORD bytes;
    fd_set ss;
    timeval touts;

    FD_ZERO(&ss);
    FD_SET(cnn,&ss);

    touts.tv_sec = 5;
    touts.tv_usec = 0;

    if(select(0,&ss,NULL,NULL,&touts) == SOCKET_ERROR || (bytes=recv(cnn,buffer,MAX_BUFFER,0))<=0)
        throw 1;
    if(bytes>0)
    {
        buffer[bytes]='\0';
        rtn = buffer;
    }
    return rtn;
}


And the try catch...

1
2
3
4
5
        try{
        buffer=servidor->recibirBuffer();
        }catch(...){
        break;
        }


The problem is, sometimes my app crashes and sometimes it works perfectly. I debuged the app and it always throw the exception but sometimes it doesn't catch it.

If i replace throw 1; with exit(1); it works perfect.

PS: Sorry for my bad english.
Mar 6, 2012 at 10:01am
For the exception case the stack has to be unwound between the point the exception was thrown and where it was caught. This can cause problems, e.g. half constructed objects being destructed and other stuff.

exit() just terminates the program without doing this stack unwinding.
Mar 6, 2012 at 3:05pm
I'm only using automatic variables on both sides.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void recibirDatosSocket(server * servidor)
{
    string buffer;
    while(1)
    {
        try{
            buffer=servidor->recibirBuffer();
        }catch(...){
            break;
        }
        servidor->sendBuffer(buffer); // echo
        cout << "Datos recibidos desde el socket: " << buffer << endl;
        if(split(buffer,"/")[0]=="salir")
            break;
    }
    TerminateThread(hComThread,0);
    terminar();
}
Mar 6, 2012 at 3:41pm
If you replace throw with return do you still get the error?
Mar 6, 2012 at 3:44pm
No, i don't get the error. It works perfectly.

1
2
    if(select(0,&ss,NULL,NULL,&touts) == SOCKET_ERROR || (bytes=recv(cnn,buffer,MAX_BUFFER,0))<=0)
        return "";


1
2
        if((buffer = servidor->recibirBuffer()) == "")
            break;
Mar 6, 2012 at 4:25pm
Well, the return will also unwind the stack back to the calling position so maybe its not that.

I've always derived my exceptions from the exception class, maybe try that?
Mar 6, 2012 at 4:27pm
Yes, i've already try that.
Mar 7, 2012 at 12:34am
Your code seems fine to me. I even tested it in a small mock project and all worked as expected.

can you short circuit your code such that you test the exception in isolation - leave out the socket stuff.


are these blocking or non blocking sockets?

also when you run your app in release/non debug mode, are you sure that your client socket (the one connecting to the server) is not closing?

is application single or multi-threaded?
Mar 7, 2012 at 5:33am
I'm using blocking sockets and it's a multi-threaded app. Without the socket stuff it works fine!

EDIT: The client "chats" with the server and it works perfect the problem is when i disconnect the client from the server.
Last edited on Mar 7, 2012 at 5:36am
Mar 7, 2012 at 6:18am
I debuged the app and it always throw the exception
Than can't be good...
Exceptions shouldn't be part of the normal flow.

but sometimes it doesn't catch it.
Dunno why that could happend. ¿Are you sure that that is what is happenning?
Mar 7, 2012 at 6:30am
I was debuggin and it said "Segmentation Fault" and prompted a Call Stack Window:

http://imageshack.us/f/825/callstack.png/
Mar 7, 2012 at 7:19am
Well, SegFault is not a c++ exception.
You may have corrupted the memory earlier.


man wrote:
1
2
3
int select(int nfds, fd_set *restrict readfds,
              fd_set *restrict writefds, fd_set *restrict errorfds,
              struct timeval *restrict timeout);


The nfds argument specifies the range of descriptors to be tested. The first nfds descriptors shall be checked in each set; that is, the descriptors from zero through nfds-1 in the descriptor sets shall be examined.
¿what if nfds=0? (as you are doing)
Mar 7, 2012 at 2:06pm
MSDN wrote:
nfds [in]
Ignored. The nfds parameter is included only for compatibility with Berkeley sockets.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx

I removed select() from my code and just used recv(). Still crashing the app.

EDIT:

My code looks like this now:

1
2
3
4
5
6
7
8
9
10
11
12
string server::recibirBuffer()
{
    string rtn;
    char buffer[MAX_BUFFER+1];
    DWORD bytes;

    bytes=recv(cnn,buffer,MAX_BUFFER,0);
    if(bytes<=0)
        throw 1;
    buffer[bytes]='\0';
    return rtn=buffer;
}


It was working fine but now still crashing.
Last edited on Mar 7, 2012 at 4:21pm
Mar 7, 2012 at 6:36pm
¿Could you provide a minimal example?
I don't think that the crash is caused by recibirBuffer(), but you triggered undefined behaviour somewhere (by instance, in split() )
Mar 7, 2012 at 6:47pm
Ok so my app is like a bridge between a client app (Written in Actionscript) and a XBee. The problem is when i'm testing with the client it recieves and sends data perfectly but if the client disconnect and my app throw the exception my app crashes. I removed the exception part and it looks like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
string server::recibirBuffer()
{
    string rtn;
    char buffer[MAX_BUFFER+1];
    DWORD bytes;
    fd_set readmask;

    FD_ZERO(&readmask);
    FD_SET(cnn,&readmask);

    if(select(0,&readmask,NULL,NULL,NULL) == 1)
    {
        unsigned long pending;
        ioctlsocket(cnn,FIONREAD,&pending); /* Numero de bytes pendientes en el buffer de entrada */
        if(!pending || (bytes=recv(cnn,buffer,MAX_BUFFER,0))<=0)
            return rtn;
        buffer[bytes]='\0';
        return rtn=buffer;
    }
    return rtn;
}


And the thread where i recieve the data:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void recibirDatosSocket(server * servidor)
{
    string buffer;
    while(1)
    {
        if((buffer=servidor->recibirBuffer()).empty())
            break;
        servidor->sendBuffer(buffer); // echo
        cout << buffer << endl;
        if(split(buffer,"/")[0]=="salir")
            break;
    }
    TerminateThread(hComThread,0);
    terminar();
}


split function:
1
2
3
4
5
6
7
8
vector<string> split(string str, const string separator)
{
    vector<string> rtn;
    unsigned int found;
    for(str+=separator;(found=str.find(separator))!=string::npos;str=str.substr(found+separator.size(),str.size()-found))
        rtn.push_back(str.substr(0,found));
     return rtn;
}


Without the exception part it works PERFECT.
PS: I'm using blocking sockets. I've trying replacing the return rtn; with throw 1; and it crashes.
Topic archived. No new replies allowed.