ошибка сегментации сокетов и потоков на языке c - PullRequest
0 голосов
/ 06 января 2019

Я работаю над клиент-серверным приложением на языке c для университетского проекта. в основном клиентский процесс отправит серверному процессу некоторую команду с заданным параметром в потоке:

-store x y (сервер сохраняет в узле списка x и y) -поиск x (поиск, если в списке есть узел со значением x, соответствующим данному x) -коррупция x z (изменить значение y узла с значением x, соответствующим данному x) -list (просто заставьте сервер распечатать весь список).

проблема в том, что каждая команда работает, кроме списка, каждый раз, когда я отправляю список от клиента, он вызывал ошибку сегментации (или иногда разрушение стека), я думаю, что это ошибка потока, потому что, если я заставлю основной поток выполнять команды все работает так же. Сразу покажите, что неисправность может быть в функции принятия. это сервер:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <pthread.h>


#define CMD_BUF 20
#define BYTE_CMD_BUF 20*sizeof(char)



typedef struct nodo
{
    char x[8];
    char y[8];
    struct nodo* next;
}nodo;

typedef nodo* lista;



lista listalocale=NULL;


//////////////////////////////////////////////operazioni su lista

lista save(char* x,char* y,lista head)
{
    if(!head)
    {
        head=malloc(sizeof(nodo));
        strcpy(head->x,x);
        strcpy(head->y,y);
        head->next=NULL;
    }
    else head->next=save(x,y,head->next);
    return head;
}


void printList(lista head)
{
    char buffer[22];
    sprintf(buffer,"(%s,%s)->",head->x,head->y);
    write(1,buffer,strlen(buffer));
    if(head->next) printList(head->next);
    else write(1,"NULL",4);
}



int isPresent(char* x,lista head)
{
    if(!head) return 0;
    else if(!strcmp(head->x,x)) return 1;
    return isPresent(x,head->next);
}



void changeValue(char* x,char* z,lista head)
{
    if(!head) return;
    else if(!strcmp(head->x,x)) strcpy(head->y,z);
    else changeValue(x,z,head->next);
    return;
}

////////////////////////////////////////////////////////////////////////elaborazione e gestione comandi
void formatMessage(char* buff,char* comm, char* val1, char* val2)
{
    comm[0]=buff[0];
    comm[1]=buff[1];
    comm[2]='\0';

    int i=3, j=0;
    while (buff[i]!=' ' & buff[i]!='_') val1[j++]=buff[i++];
    val1[j]='\0';

    j=0;
    while (buff[i]!='_') val2[j++]=buff[i++];
    val2[j]='\0';   
}


void *processCommandServer(void *arg)
{
    char buff[20],com[3],p1[8],p2[8];
    int sd=*(int*)arg;


    if( read(sd,buff,BYTE_CMD_BUF)<1 ) perror("COMANDO SCONOSCIUTO");

    formatMessage(buff,com,p1,p2);


    if(!strcmp(com,"li")) printList(listalocale);
    else if(!strcmp(com,"se")) isPresent(p1,listalocale);
    else if(!strcmp(com,"st")) listalocale=save(p1,p2,listalocale);
    else if(!strcmp(com,"co")) changeValue(p1,p2,listalocale);
    return NULL;
} 

/////////////////////////////////////////////////////////////// gestione connessione

void assegnaIndirizzo(int sd,char* indirizzo,int porta)
{
    struct sockaddr_in  server;

     server.sin_family=AF_INET;
     server.sin_port=htons(porta);
     server.sin_addr.s_addr=inet_addr(indirizzo);

    if(bind(sd,(struct sockaddr*)&server , sizeof( server))<0) 
        perror("ERRORE CONNESSIONE");
}


int creaSocketServer(char* indirizzo,int porta)
{
    int sd=socket(PF_INET,SOCK_STREAM,0);

    if(sd<=0) perror("ERRORE CREAZIONE");
    else assegnaIndirizzo(sd,indirizzo,porta);

    return sd;
}


int waitConnection(int sd)
{
    struct sockaddr_in address;
    socklen_t l=sizeof(address);
    int sd2;
    pthread_t tid=0;

    listen(sd,5);

    sd2=accept(sd,(struct sockaddr*)&address,&l);                  //commenta se vuoi eliminare thread
    pthread_create(&tid,NULL,processCommandServer,(void*) &sd2);   //commenta se vuoi eliminare thread

    while(1)
    {
        sd2=accept(sd,(struct sockaddr*)&address,&l);
        //processCommandServer((void*)&sd2);                            //scommenta se vuoi eliminare thread
        pthread_join(tid,NULL);                                         //commenta se vuoi eliminare thread
        pthread_create(&tid,NULL,processCommandServer,(void*) &sd2);    //commenta se vuoi eliminare thread
    }
}
/////////////////////////////////////////////////////////////////

int main(int argc, char const *argv[])
{
    int sd=creaSocketServer("192.168.1.195",atoi(argv[1]));
    waitConnection(sd);
}

а это клиент:

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>


#define CMD_BUF 20
#define BYTE_CMD_BUF 20*sizeof(char)


/////////////////////////////////////////////////////////////////gestione connessioni
void sendData(int sd, char* comando)
{
    int res=write(sd,comando,strlen(comando)*sizeof(char));     //invia comando

    if(res > 0) write(STDOUT_FILENO,"Message Delivered\n",sizeof("Message Delivered\n"));   //controlla esito invio comando
    else perror("ERROR");
}

void connettiSocket(int sd,const char* indirizzo,int porta)
{
    struct sockaddr_in client;   

    client.sin_family=AF_INET;                      //imposta connessione tcp
    client.sin_port=htons(porta);                   //imposta porta
    client.sin_addr.s_addr=inet_addr(indirizzo);    //imposta indirizzo

    if( connect(sd,(struct sockaddr*)&client,sizeof(client)) <0 )  //si connette a client e controlla errori 
        perror("ERRORE CONNESSIONE");
}

int creaSocketClient(const char* indirizzo,int porta)
{
    int sd=socket(PF_INET,SOCK_STREAM,0);       //crea socket

    if(sd<=0) perror("ERRORE CREAZIONE");       //controlla errori
    else connettiSocket(sd,indirizzo, porta);

    return sd;
}

///////////////////////////////////////////////////////////////////////////comandi
void store(const char* x, const char* y,const char* ip, int porta)
{
    int sd=creaSocketClient(ip,porta);  //crea connessione

    char cmd[CMD_BUF];                  //buffer comando
    sprintf(cmd,"st %s %s_",x,y);       //formatta comando

    sendData(sd,cmd);                   
}

void corrupt(const char* x, const char* z,const char* ip, int porta) //vedi store
{
    int sd=creaSocketClient(ip,porta);

    char cmd[CMD_BUF];
    sprintf(cmd,"co %s %s_",x,z);

    sendData(sd,cmd);
}

void search(const char* x,const char* ip, int porta)//vedi store
{
    int sd=creaSocketClient(ip,porta);

    char cmd[CMD_BUF];
    sprintf(cmd,"se %s_",x);

    sendData(sd,cmd);
}

void list(const char* ip, int porta)//vedi store
{
    int sd=creaSocketClient(ip,porta);

    char cmd[CMD_BUF];
    sprintf(cmd,"li_");

    sendData(sd,cmd);
}
////////////////////////////////////////////////////////////////////////

int main(int argc, char const *argv[])
{
         if(!strcmp(argv[3],"store")   & argc==6) store(argv[4],argv[5],argv[1],atoi(argv[2]));
    else if(!strcmp(argv[3],"corrupt") & argc==6) corrupt(argv[4],argv[5],argv[1],atoi(argv[2]));
    else if(!strcmp(argv[3],"search")  & argc==5) search(argv[4],argv[1],atoi(argv[2]));
    else if(!strcmp(argv[3],"list")    & argc==4) list(argv[1],atoi(argv[2]));
    else perror("comando non valido");  
}

это вывод strace, если я отправляю 2 команды store и 1 list list:

execve("./a.out", ["./a.out", "5900"], 0x7ffff0e72298 /* 25 vars */) = 0
brk(NULL)                               = 0x555c05424000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffd14dbd370) = -1 EINVAL (Argomento non valido)
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (File o directory non esistente)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=228153, ...}) = 0
mmap(NULL, 228153, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f066cef9000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libpthread.so.0", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\340f\0\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=155408, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f066cef7000
lseek(3, 808, SEEK_SET)                 = 808
read(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32) = 32
mmap(NULL, 131528, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f066ced6000
mmap(0x7f066cedc000, 61440, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x6000) = 0x7f066cedc000
mmap(0x7f066ceeb000, 24576, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x15000) = 0x7f066ceeb000
mmap(0x7f066cef1000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1a000) = 0x7f066cef1000
mmap(0x7f066cef3000, 12744, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f066cef3000
close(3)                                = 0
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000C\2\0\0\0\0\0"..., 832) = 832
lseek(3, 792, SEEK_SET)                 = 792
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\201\336\t\36\251c\324\233E\371SoK\5H\334"..., 68) = 68
fstat(3, {st_mode=S_IFREG|0755, st_size=2136840, ...}) = 0
lseek(3, 792, SEEK_SET)                 = 792
read(3, "\4\0\0\0\24\0\0\0\3\0\0\0GNU\0\201\336\t\36\251c\324\233E\371SoK\5H\334"..., 68) = 68
lseek(3, 864, SEEK_SET)                 = 864
read(3, "\4\0\0\0\20\0\0\0\5\0\0\0GNU\0\2\0\0\300\4\0\0\0\3\0\0\0\0\0\0\0", 32) = 32
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f066cd12000
mprotect(0x7f066cd34000, 1671168, PROT_NONE) = 0
mmap(0x7f066cd34000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x22000) = 0x7f066cd34000
mmap(0x7f066ce7f000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x16d000) = 0x7f066ce7f000
mmap(0x7f066cecc000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b9000) = 0x7f066cecc000
mmap(0x7f066ced2000, 13888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f066ced2000
close(3)                                = 0
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f066cd0f000
arch_prctl(ARCH_SET_FS, 0x7f066cd0f740) = 0
mprotect(0x7f066cecc000, 16384, PROT_READ) = 0
mprotect(0x7f066cef1000, 4096, PROT_READ) = 0
mprotect(0x555c0363d000, 4096, PROT_READ) = 0
mprotect(0x7f066cf5a000, 4096, PROT_READ) = 0
munmap(0x7f066cef9000, 228153)          = 0
set_tid_address(0x7f066cd0fa10)         = 10560
set_robust_list(0x7f066cd0fa20, 24)     = 0
rt_sigaction(SIGRTMIN, {sa_handler=0x7f066cedc130, sa_mask=[], sa_flags=SA_RESTORER|SA_SIGINFO, sa_restorer=0x7f066cee83c0}, NULL, 8) = 0
rt_sigaction(SIGRT_1, {sa_handler=0x7f066cedc1d0, sa_mask=[], sa_flags=SA_RESTORER|SA_RESTART|SA_SIGINFO, sa_restorer=0x7f066cee83c0}, NULL, 8) = 0
rt_sigprocmask(SIG_UNBLOCK, [RTMIN RT_1], NULL, 8) = 0
prlimit64(0, RLIMIT_STACK, NULL, {rlim_cur=8192*1024, rlim_max=RLIM64_INFINITY}) = 0
socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
bind(3, {sa_family=AF_INET, sin_port=htons(5900), sin_addr=inet_addr("192.168.1.195")}, 16) = 0
listen(3, 5)                            = 0
accept(3, {sa_family=AF_INET, sin_port=htons(60902), sin_addr=inet_addr("192.168.1.195")}, [16]) = 4
mmap(NULL, 8392704, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS|MAP_STACK, -1, 0) = 0x7f066c50e000
mprotect(0x7f066c50f000, 8388608, PROT_READ|PROT_WRITE) = 0
brk(NULL)                               = 0x555c05424000
brk(0x555c05445000)                     = 0x555c05445000
clone(child_stack=0x7f066cd0dfb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f066cd0e9d0, tls=0x7f066cd0e700, child_tidptr=0x7f066cd0e9d0) = 10562
accept(3, {sa_family=AF_INET, sin_port=htons(60904), sin_addr=inet_addr("192.168.1.195")}, [16]) = 5
clone(child_stack=0x7f066cd0dfb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f066cd0e9d0, tls=0x7f066cd0e700, child_tidptr=0x7f066cd0e9d0) = 10564
accept(3, {sa_family=AF_INET, sin_port=htons(60906), sin_addr=inet_addr("192.168.1.195")}, [16]) = 6
clone(child_stack=0x7f066cd0dfb0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID, parent_tidptr=0x7f066cd0e9d0, tls=0x7f066cd0e700, child_tidptr=0x7f066cd0e9d0) = 10566
accept(3,  <unfinished ...>)            = ?
+++ killed by SIGSEGV (core dumped) +++
Segmentation Fault

1 Ответ

0 голосов
/ 07 января 2019

ошибка была в функции formatMessage, список не получил параметров, поэтому он имеет 3 символа: функция начала копировать команду (первые 2 символа) и перейти к 4-му числу, выходящему за пределы массива команд списка. А также ваши советы, где очень полезно

...