dcsimg
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 2 12 LastLast
Results 1 to 15 of 21

Thread: SIGSEGVs, missing parts of input

  1. #1
    Join Date
    Mar 2014
    Posts
    23

    Question SIGSEGVs, missing parts of input

    Hello wise people!

    Got a problem with my winsock client program. It looses parts of input. Here's the important (IMO) part of the code:
    Code:
       
    ...
     string nickname;
        if(connect(socketDeskryptor,(struct sockaddr*)&dest_addr,sizeof(struct sockaddr))==-1)
        {
            cout<<"ERROR! Failed to connect to the server error nr "<<WSAGetLastError()<<endl;
            system("pause");
            exit(1);
        }
        else
        {
            cout<<"connected!"<<endl;
            ReceiverHandle=CreateThread(NULL,0,ReceiverThread,&socketDeskryptor,0,NULL); // a thread to handle server response
            cout<<"You have to select a nickname to use first(enter blank to use your IP as nickname)"<<endl;
            NICKNAME_SELECTION:
            nickname.clear();
            cin.ignore();
            getline(cin,nickname);
            if(nickname.length()>20)
            {
                cout<<"You have exceeded the maximum ammount of 20 characters to be used as your nickname.Try again."<<endl;
                goto NICKNAME_SELECTION; 
            }
            send(socketDeskryptor,nickname.c_str(),20,0);
            nickname.clear();
        }
        string message;
        while(1) //message loop
        {
    
        message.clear();
        cin.ignore();
        getline(cin,message);
        if(message=="EXIT")
        {
            break;
        }
        if(message.length()>200)
        {
            cout<<"You've exceeded the maximum ammount of 200 characters in a single message.Message won't be sent"<<endl;
            message="";
            continue;
        }
        cout<<"This is the message to send: "<<message<<endl;
        send(socketDeskryptor,message.c_str(),200,0);
    
    
        }
        return 0;
    }
    During debugging it also shows multiple SIGSEGV errors, even though it compiles just fine. Also the nickname selection part seems to work fine, i decided to include it for reference. The problem lies in the message loop. I'll give you an example console output.

    connected!
    You have to select a nickname to use first(enter blank to use your IP as a nickname)
    XXX
    server response: 192.168.1.115 changed name to XXX!
    Hello my name is George
    this is the message to send: ello my name i George
    server response: XXX said: ello my name i George

    As you can see it "bites off" single letters from the message. And I have no idea why . I've been searching for the solution for en ethernity now.
    Name:  x240-oI6.jpg
Views: 174
Size:  7.7 KB

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,620

    Re: SIGSEGVs, missing parts of input

    Victor Nijegorodov

  3. #3
    Join Date
    Mar 2014
    Posts
    23

    Re: SIGSEGVs, missing parts of input

    In case you wanted the entire source code:
    Code:
    #include <winsock2.h>
    #include <cstdio>
    #include <iostream>
    #include <windef.h>
    #include <windows.h>
    #include <cstring>
    
    using namespace std;
    
    DWORD WINAPI ReceiverThread(LPVOID ClientSocketDeskryptor) //Thread used for handling server response
    {
        char message[220];
        int CSD = *(reinterpret_cast<int*>(ClientSocketDeskryptor)); //stores socket deskryptor
        int numbytes;
        while(1)
        {
            memset(message,'\0',220);
            numbytes=recv(CSD,message,220,0);
            if(numbytes==0)
            {
                break;
            }
            if(numbytes==-1)
            {
                cout<<"Error receiving message error nr "<<WSAGetLastError()<<endl;
                continue;
            }
    
            if(message[0]=='\0')
            {
                continue;
            }
            cout<<message<<endl;
            cin.ignore();
            cout<<"loop"<<endl;
        }
        cout<<"Receiver exiting..."<<endl;
        return 0;
    }
    
    int main()
    {
        HANDLE ReceiverHandle;
        WSADATA wsaData;
        if(WSAStartup(MAKEWORD(1,1),&wsaData)!=0)
        {
            fprintf(stderr,"WSAStartup failed.\n");
            system("pause");
            exit(1);
        }
    
        int socketDeskryptor;
        sockaddr_in dest_addr;
    
    
        socketDeskryptor=socket(AF_INET,SOCK_STREAM,0);
        string destination_IP;
        int destination_port;
        cout<<"please specify the IP and port to connect to"<<endl;
        cout<<"IP: ";
        cin>>destination_IP;
        cout<<"port: ";
        cin>>destination_port;
    
        dest_addr.sin_family=AF_INET;
        dest_addr.sin_port=htons(destination_port);
        dest_addr.sin_addr.s_addr=inet_addr(destination_IP.c_str());
        memset(dest_addr.sin_zero,'\0',8);
        string nickname;
        if(connect(socketDeskryptor,(struct sockaddr*)&dest_addr,sizeof(struct sockaddr))==-1)
        {
            cout<<"ERROR! Failed to connect to the server error nr "<<WSAGetLastError()<<endl;
            system("pause");
            exit(1);
        }
        else
        {
            cout<<"connected!"<<endl;
            ReceiverHandle=CreateThread(NULL,0,ReceiverThread,&socketDeskryptor,0,NULL);
            cout<<"You have to select a nickname to use first(enter blank to use your IP as nickname)"<<endl;
            NICKNAME_SELECTION:
            nickname.clear();
            cin.ignore();
            getline(cin,nickname);
            cout<<"getl nickname="<<nickname<<endl;
            if(nickname.length()>20)
            {
                cout<<"You have exceeded the maximum ammount of 20 characters to be used as your nickname.Try again."<<endl;
                goto NICKNAME_SELECTION;
            }
            send(socketDeskryptor,nickname.c_str(),20,0);
            nickname.clear();
        }
        string message;
        while(1)
        {
    
        message.clear();
        cin.ignore();
        getline(cin,message);
        if(message=="EXIT")
        {
            break;
        }
        if(message.length()>200)
        {
            cout<<"You've exceeded the maximum ammount of 200 characters in a single message.Message won't be sent"<<endl;
            message="";
            continue;
        }
        cout<<"This is the message to send: "<<message<<endl;
        send(socketDeskryptor,message.c_str(),200,0);
    
    
        }
        return 0;
    
    
    }

  4. #4
    Join Date
    Mar 2014
    Posts
    23

    Re: SIGSEGVs, missing parts of input

    Heh, thank you but I already know what a Segmentation fault is. In fact I've been using this exact site before. The question is how do I fix it. I see no buffer overflows, null-ptr dereferences or invalid memory access attempts in my code.
    In fact the SIGSEGV exception seems to be a secondary matter as it only happens during debugging. Other than than the client runs fine and terminates properly. If it wasn't for the missing input I probably wouldn't even mention it, but perhaps these two problems are connected somehow...

  5. #5
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,620

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by Fides Facit Fortis View Post
    Heh, thank you but I already know what a Segmentation fault is. In fact I've been using this exact site before. The question is how do I fix it. I see no buffer overflows, null-ptr dereferences or invalid memory access attempts in my code.
    How did you check it?
    Did you debug your code step-by-step (line-by-line) and looked at the debur/watch window to control all the variable values/arrays and so on?
    Victor Nijegorodov

  6. #6
    Join Date
    Mar 2014
    Posts
    23

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by VictorN View Post
    How did you check it?
    Did you debug your code step-by-step (line-by-line) and looked at the debur/watch window to control all the variable values/arrays and so on?
    Pretty much. I placed a breakpoint in every single line and added every variable to the watch list. At the end shortly after sending the 1st message(nickname) the client crashes but only in debug mode.Running the program normally doesn't end up with a crash. Another thing that bothers me is that sometimes this appears in destination_id's value field...

    The program being debugged was signaled while in a function called from GDB.
    GDB has restored the context to what it was before the call.
    To change this behavior use "set unwindonsignal off".
    Evaluation of the expression containing the function
    (std::string::c_str() const) will be abandoned.
    Program received signal SIGSEGV, Segmentation fault.
    0x00423044 in std::string::c_str() const ()

    dunno what that means. The variable has the right value (I checked it with a cout and also it connects to the server so the IP must be right) and other than that seems to work fine.
    Last edited by Fides Facit Fortis; September 15th, 2015 at 10:04 AM.

  7. #7
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,620

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by Fides Facit Fortis View Post
    ... I'll give you an example console output.

    connected!
    You have to select a nickname to use first(enter blank to use your IP as a nickname)
    XXX
    server response: 192.168.1.115 changed name to XXX!
    Hello my name is George
    this is the message to send: ello my name i George
    server response: XXX said: ello my name i George

    As you can see it "bites off" single letters from the message. And I have no idea why . I've been searching for the solution for en ethernity now.
    Name:  x240-oI6.jpg
Views: 174
Size:  7.7 KB
    Is the "XXX" the real nickname you enter?
    Or it is just a placeholder and your real nickname is 20 character long?

    Anyway, if you expect to use nickname up to 20 character long and use plain char array for this, then you must define the array length at least 21 and set the terminating NULL at the end
    Victor Nijegorodov

  8. #8
    Join Date
    Mar 2014
    Posts
    23

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by VictorN View Post
    Is the "XXX" the real nickname you enter?
    Or it is just a placeholder and your real nickname is 20 character long?

    Anyway, if you expect to use nickname up to 20 character long and use plain char array for this, then you must define the array length at least 21 and set the terminating NULL at the end
    Actually I am not even using char arrays, I'm using strings which I then pass to the send() function using string::c_str() which returns the C string version(which is a null-terminated char array)
    Code:
    string nickname; //this is a string
    ...
      send(socketDeskryptor,nickname.c_str(),20,0);
    And yes, I am actually using XXX as my nickname for the purpose of testing.
    Last edited by Fides Facit Fortis; September 15th, 2015 at 12:40 PM.

  9. #9
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,620

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by Fides Facit Fortis View Post
    Actually I am not even using char arrays, I'm using strings which I then pass to the send() function using string::c_str() which returns the C string version(which is a null-terminated char array)
    Then why don't you get rid of using plain character arrays?
    Victor Nijegorodov

  10. #10
    Join Date
    Mar 2014
    Posts
    23

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by VictorN View Post
    Then why don't you get rid of using plain character arrays?
    if you mean the only buffer I'm using
    Code:
    ...
    DWORD WINAPI ReceiverThread(LPVOID ClientSocketDeskryptor) //Thread used for handling server response
    {
        char message[220]; //the only buffer in the entire client
        int CSD = *(reinterpret_cast<int*>(ClientSocketDeskryptor)); //stores socket deskryptor
        int numbytes;
        while(1)
        {
            memset(message,'\0',220);
            numbytes=recv(CSD,message,220,0)
    ...
    That's because I've got no idea how to properly pass a string to the recv() function.
    Still, the buffer couldn't be overflowing. recv is set to only accept 220 bytes, which is exactly the buffer size. Right?

  11. #11
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,620

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by Fides Facit Fortis View Post
    ...
    Still, the buffer couldn't be overflowing. recv is set to only accept 220 bytes, which is exactly the buffer size. Right?
    Right,
    but the 220-th character written into the buffer will overwrite the terminating NULL character, so the buffer could now contain the garbage beginning with the 221-th position!
    Victor Nijegorodov

  12. #12
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,030

    Re: SIGSEGVs, missing parts of input

    How is the message array used after recv() ? If 220 bytes were received, then message[] won't be null-terminated which may be as required or may not depending upon what the following code expects.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++17 Compiler: Microsoft VS2019 (16.5.1)

  13. #13
    Join Date
    Mar 2014
    Posts
    23

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by 2kaud View Post
    How is the message array used after recv() ? If 220 bytes were received, then message[] won't be null-terminated which may be as required or may not depending upon what the following code expects.
    Quote Originally Posted by VictorN View Post
    Right,
    but the 220-th character written into the buffer will overwrite the terminating NULL character, so the buffer could now contain the garbage beginning with the 221-th position!
    Sorry for not responding but I was away from home yesterday.
    Following your advice I changed this part of code:
    Code:
    DWORD WINAPI ReceiverThread(LPVOID ClientSocketDeskryptor) //Thread used for handling server response
    {
        char message[220];
        int CSD = *(reinterpret_cast<int*>(ClientSocketDeskryptor)); //stores socket deskryptor
        int numbytes;
        while(1)
        {
            memset(message,'\0',221);
            numbytes=recv(CSD,message,220,0);
    to this:
    Code:
    DWORD WINAPI ReceiverThread(LPVOID ClientSocketDeskryptor) //Thread used for handling server response
    {
        char message[221];
        int CSD = *(reinterpret_cast<int*>(ClientSocketDeskryptor)); //stores socket deskryptor
        int numbytes;
        while(1)
        {
            memset(message,'\0',220);
            numbytes=recv(CSD,message,220,0);
            message[220]='\0';
    Basically i added one extra character to message and made sure it's null. TBH it does seems like it helped a bit because it no longer takes away the characters from the middle of input, but it still takes away 1 or 2 characters at the beginning.

    connected!
    You have to select a nickname to use first(enter blank to use your IP as nickname)
    XXX
    server response: 192.168.1.115 changed name to XX!
    Hello my name is George
    message to send: llo my name is George
    server response: XX said: llo my name is George
    123456789012345678901234567890
    message to send: 3456789012345678901234567890
    server response: XX said: 3456789012345678901234567890
    Last edited by Fides Facit Fortis; September 18th, 2015 at 04:35 AM.

  14. #14
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    19,620

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by Fides Facit Fortis View Post
    ...
    connected!
    You have to select a nickname to use first(enter blank to use your IP as nickname)
    XXX
    server response: 192.168.1.115 changed name to XX!
    Hello my name is George
    message to send: llo my name is George

    server response: XX said: llo my name is George
    123456789012345678901234567890
    message to send: 3456789012345678901234567890

    server response: XX said: 3456789012345678901234567890e
    The problem with disappeared 2 characters at the beginning happens between the
    Code:
        getline(cin,message);
    and
    Code:
     cout<<"This is the message to send: "<<message<<endl;
    you should debug this code block to see what happens with the variable message.
    Last edited by VictorN; September 18th, 2015 at 05:12 AM.
    Victor Nijegorodov

  15. #15
    Join Date
    Mar 2014
    Posts
    23

    Re: SIGSEGVs, missing parts of input

    Quote Originally Posted by VictorN View Post
    The problem with disappeared 2 characters at the beginning happens between the
    Code:
        getline(cin,message);
    and
    Code:
     cout<<"This is the message to send: "<<message<<endl;
    you should debug this code block to see what happens with the variable message.
    Well, I did it. I debugged the nickname part too because sometimes it takes away the first 1 or 2 characters from the nickname as well. Here's what I've got:

    The nickname part:
    Code:
            getline(cin,nickname);// [BREAKPOINT 1]
            cout<<"getl nickname="<<nickname<<endl;// [BREAKPOINT 2]
            if(nickname.length()>20) //[BREAKPOINT 3]
            {
                cout<<"You have exceeded the maximum ammount of 20 characters to be used as your nickname.Try again."<<endl;
                goto NICKNAME_SELECTION;
            }
            cout<<"nickname "<<nickname<<endl; [BREAKPOINT 4]
            send(socketDeskryptor,nickname.c_str(),20,0); [BREAKPOINT 5]
    BP1: (the input was "XXX")
    message value: type=std::string
    nickname value: static npos = <optimized out>, _M_dataplus (no idea what this means)
    BP 2: (SIGSEGV)
    message value : ""
    nickname value: ""
    BP3:
    message value: ""
    nickname value: static npos = <optimized out>, _M_dataplus
    BP4:
    message value: "XX"
    nickname value: "XX"
    BP5:
    message value: ""
    nickname value: static npos = <optimized out>, _M_dataplus

    the message part:
    Code:
        string message;
        while(1)
        {
    
        message="";
        cin.ignore();
        getline(cin,message); //[BREAKPOINT 1]
        if(message=="EXIT") //[BREAKPOINT 2]
        {
            break;
        }
        if(message.length()>200)
        {
            cout<<"You've exceeded the maximum ammount of 200 characters in a single message.Message won't be sent"<<endl;
            message="";
            continue;
        }
        cout<<"This is the message to send: "<<message<<endl; //[BREAKPOINT 3]
        send(socketDeskryptor,message.c_str(),200,0); //[BREAKPOINT 4]
    BP1: (the input was "Hello my name is George")
    message value: type=std::string
    nickname value: static npos = <optimized out>, _M_dataplus
    BP2: (SIGSEGV)
    message value: type=std::string
    nickname value: static npos=<optimized out>, _M_dataplus
    BP3:
    message value: "llo my name is George"
    nickname value: "llo my name is George"
    BP4:
    message value: type=std::string
    nickname value: static npos = <optimized out>, _M_dataplus

    Strange, huh?

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width




On-Demand Webinars (sponsored)