简体   繁体   中英

Segmentation fault with client C++ program

I am having some difficulty with finding out how to correct the segmentation fault. client.cpp

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <arpa/inet.h>

using namespace std;

int call_socket(char *hostname, unsigned short portnum)
{
    struct sockaddr_in sa;
    struct hostent *hp;
    int a;
    int s;

    if ((hp = gethostbyname(hostname)) == NULL)
    {
        errno = ECONNREFUSED;
        return(-1);
    }

    memset(&sa, 0, sizeof(sa));
    memcpy((char*) &sa.sin_addr, hp->h_addr, hp->h_length);
    sa.sin_family = hp->h_addrtype;
    sa.sin_port = htons((u_short)portnum);

    if ((s=socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0)
    {
        return(-1);
    }
    if (connect(s, (struct sockaddr*)&sa, sizeof (sa)) < 0)
    {
        close(s);
        return(-1);
    }
    return(s);
}

int main(int argc, char* argv[])
{
    int n;
    int s;
    int b;
    char username[256];
    string hostname;
    string usern;
    string terminated = "Server Terminated";
    string doesnotexist = "does not exist.";

    hostname = "localhost";
    
    char *hostn[hostname.size()+1];
    strcpy(*hostn, hostname.c_str());

    cout << "Enter a server port number: " << endl;
    cin >> s; 
    while (s <2000 || s > 65535)
    {
        cout << "Server port number must be between 2000 and 65535. Please enter the server port number again." << endl;
        cin >> s;
    }

    if ((b = call_socket(*hostn,s)) < 0)
    {
        perror("call Socket");
        exit(1);
    }

    cout << "Enter a user name: " << endl;
    cin >> usern;
    strcpy(username, usern.c_str());
    n = write(b, username, strlen(username));
    if (n < 0)
    {
        cout << "Error writing to socket" << endl;
    }

    bzero(username, 256);
    n = read(b,username,255);
    if (n < 0)
    {
        cout << "Error reading from socket" << endl;
    }

    if (username == terminated)
    {
        printf("%s\n",username);
    }
    else if (username == doesnotexist)
    {
        cout << "The username: " << usern << ", ";
        printf("%s\n",username);
    }
    else
    {
        cout << "The public key for " << usern << " is: ";
        printf("%s\n",username);
    }

    close(b);
    return 0;
}

I tried valgrind and got: Conditional jump or move depends on uninitialised value(s), Use of uninitialised value of size 8, Invalid write of size 8. As I am unexperienced with valgrind, I don't really know how to fix it.

Your problem is almost certainly here:

char *hostn[hostname.size()+1];
strcpy(*hostn, hostname.c_str());

This has several issues:

  1. hostn is a variable-length-array, which is not a standard part of C++
  2. hostn is an array of char* , not an array of char
  3. The pointers in hostn are uninitialized, and thus don't point anywhere useful.
  4. You pass the first element of hostn to strcpy as the destination

Since strcpy will attempt to dereference the pointer passed to it and that pointer is uninitialized, that means your program's behavior is undefined.


Note that all of this could be avoided easily. Just get rid of hostn entirely. It's not serving any purpose beyond what hostname.c_str() already serves. Simply change call_socket to accept a const char* instead of a char* , and you can call it directly using hostname.c_str() (ie call_socket(hostname.c_str(), s) )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM