gpt4 book ai didi

c - 在 C 中预订客户端-服务器时检测到堆栈崩溃

转载 作者:行者123 更新时间:2023-11-30 15:56:22 26 4
gpt4 key购买 nike

嗨,我在 C 语言的客户端服务器程序中遇到了这个问题。这应该是一个非常简单的预订系统...请有人可以帮助我,我不知道如何修复(C 中的第一个项目)。提前致谢

Client.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>


#define ERRORE -1
#define FLAG 0
#define SIZE 128
#define R 3
#define C 5

typedef struct {
int response_channel;
int service_code;
} request;


typedef struct {
long mtype;
request req;
} request_msg;


typedef struct {
long mtype;
int posti[R][C];
} response_msg;

/*strutture per cancella*/
typedef struct {
int response_channel;
int service_code;
char codice[5];
} request_canc;


typedef struct {
long mtype;
request_canc req;
} request_msg_canc;

typedef struct {
long mtype;
char risp[256];
} response_msg_canc;
//************************************************//

/* strutture per prenota*/
typedef struct {
int response_channel;
int service_code;
int posti[R][C];
} request_pren;

typedef struct {
long mtype;
request_pren req;
} request_msg_pren;

//**********************//



int my_id_coda,id_coda, ret, STATUS;
long key;
int sala[R][C];

request_msg request_message;
response_msg response_message;

/*variabili per cancella*/
request_msg_canc request_message_canc;

request_msg_pren posti_p;

void visualizza();
void prenota();
void cancella();
int menu();

main(int argc, char *argv[]) {
int scelta,ris;

key = getpid();

my_id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( my_id_coda == -1){
my_id_coda = msgget(key, IPC_CREAT|0666);
ret = msgctl(my_id_coda,IPC_RMID,0);
my_id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( my_id_coda == -1 ){
printf("cannot install client queue, please check with the problem\n");
exit(-1);
}
}


id_coda = msgget(50, IPC_CREAT|0666);
if( id_coda == -1 ){
printf("cannot open server queue, please check with the problem\n");
exit(-1);
}

/*qui mancava il richiamo al menu*/

do{

int a;
printf("1 visualizza;\n");
printf("2 prenota;\n");
printf("3 cancella;\n");
printf("4 esci;\n");
scanf("%d",&a);

scelta = a;

switch(scelta) {
case 1: visualizza(); break;
case 2: prenota(); break;
case 3: cancella(); break;
}
}while(scelta != 4);
ris=msgctl(my_id_coda,IPC_RMID,0);
if(ris==-1)printf("Errore nella chiamata msgctl");
exit(-1);

}/* end main*/


void visualizza() {
int i,j;
request_message.mtype = 1;
request_message.req.service_code = 1;
request_message.req.response_channel = my_id_coda;
printf("response channel has id %d\n",my_id_coda);

if ( msgsnd(id_coda, &request_message, sizeof(request), FLAG) == -1 ) {
printf("cannot send request to the server\n");
exit(-1);
}


if ( msgrcv(my_id_coda, &response_message, sizeof(response_msg), 1, FLAG) == -1) {
printf("error while receiving the server response, please check with the problem\n");
exit(-1);
}
else {

memcpy((char*)sala,(char*)response_message.posti,128);
printf("\nla sala è:\n");
for(i=0;i<R;i++){
for(j=0;j<C;j++){
printf("%d ",sala[i][j]);
}
printf("\n");
}

}
}

void prenota(){

int i,j;
int numero=0;
int fila=0;
int poltrona=0;
response_msg_canc risposta_codice;

for(i=0;i<R;i++)
for(j=0;j<C;j++)
posti_p.req.posti[i][j]=0;
numero=0;
while(numero>R*C || numero<=0){
printf("Digitare il numero di posti che si vuole prenotare compreso tra 1 e %d\n",R*C);
scanf("%d",&numero);
}
for(i=0;i<numero;i++){
printf("Digitare il %d° posto nel formato 'fila poltrona' con fila compresa tra 1..%d e poltrona tra 1..%d \n",i+1,R,C);
scanf("%d%d",&fila,&poltrona);
/*scanf("%d",&fila);
scanf("%d",&poltrona);*/
if(fila<=0 || fila>R || poltrona<=0 || poltrona>C){
printf("ERRORE\n");
i--;
}
else {posti_p.req.posti[fila-1][poltrona-1]=1;}
}

for(i=0;i<R;i++){
for(j=0;j<C;j++){
printf("%d",posti_p.req.posti[i][j]);
}
printf("\n");
}
posti_p.mtype = 2;
posti_p.req.service_code = 2;

posti_p.req.response_channel = my_id_coda;

if ( msgsnd(id_coda, &posti_p, sizeof(request_pren), FLAG) == -1 ) {
printf("cannot send request to the server\n");
exit(-1);
}

if ( msgrcv(my_id_coda, &risposta_codice, sizeof(response_msg_canc), 2, FLAG) == -1) {
printf("error while receiving the server response, please check with the problem\n");
exit(-1);
}
printf("%s\n",risposta_codice.risp);

}


/* metodo cancella*/

void cancella(){
int i,j;
char preno[5];
response_msg_canc risposta;

request_message_canc.mtype = 3;
request_message_canc.req.service_code = 3;

printf("Inserire codice prenotazione da cancellare:");
scanf("%s",preno);
strcpy(request_message_canc.req.codice,preno);


request_message_canc.req.response_channel = my_id_coda;
printf("response channel has id %d\n",my_id_coda);

if ( msgsnd(id_coda, &request_message_canc, sizeof(request_canc), FLAG) == -1 ) {
printf("cannot send request to the server\n");
exit(-1);
}

if ( msgrcv(my_id_coda, &risposta,sizeof(response_msg_canc), 3, FLAG) == -1) {
printf("error while receiving the server response, please check with the problem\n");
exit(-1);
}
risposta.risp[255]='\0';
printf("%s\n",risposta.risp);
}

服务器.c

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/signal.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/shm.h>
#include <math.h>
#include<stdlib.h>
#include<string.h>
#include <sys/sem.h>

#define ERRORE -1
#define FLAG 0
#define SIZE 128
#define R 3
#define C 5
#define CINEMA "prenotazione"
#define STDOUT 1

typedef struct {
int response_channel;
int service_code;
} request;

typedef struct {
int response_channel;
int service_code;
char codice[5];
} request_canc;

typedef struct {
long mtype;
request_canc req;
} request_msg_canc;

typedef struct {
long mtype;
request req;
} request_msg;


typedef struct {
long mtype;
int posti[R][C];
} response_msg;

typedef struct {
char pren[6];
} codice;

typedef struct {
long mtype;
char risp[256];
} response_msg_canc;

/* strutture per prenota*/
typedef struct {
int response_channel;
int service_code;
int posti[R][C];
} request_pren;

typedef struct {
long mtype;
request_pren req;
} request_msg_pren;


//**********************//


codice prenotazioni[R][C];
int id_coda, ret;
long key = 50;


request_msg request_message;
request_msg *new_message;
pthread_t tid;
response_msg response_message;

request_msg_canc request_mes_canc;
request_msg_canc *new_mes_canc;

request_msg_pren request_mes_pren;
request_msg_pren *new_mes_pren;


int ds_shm;

int id_sem;

void ito(int,char*);
int crea_init_sem(key_t,int);
void elimina_sem(int);
int sem_wait(int);
int sem_signal(int);
void visualizza(request_msg*);
void prenota (request_msg_pren*);
void cancella (request_msg_canc*);


main(int argc, char *argv[]) {
codice prenot[3][5];

int sd,size,occ,i,j,status,eli;
long chiave=10,chiave_sem=50;

char buff[5],app[5],*p,*scorri_mem;


sd=open(CINEMA,O_RDONLY);


ds_shm = shmget(chiave,sizeof(codice[3][5]),IPC_CREAT|0666);
if( ds_shm == -1) {printf("Errore nella chiamata shmget\n"); exit(1);}

p = shmat(ds_shm, 0, SHM_W);
if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}
scorri_mem=p;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
size=read(sd,buff,5);
memcpy((char*)app,(char*)buff,size);
strncpy(scorri_mem,app,5);
*(scorri_mem+5)='\0';
printf("%s",scorri_mem);
scorri_mem+=6;
}
}
id_sem=crea_init_sem(chiave_sem,1);


id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( id_coda == -1){
id_coda = msgget(key, IPC_CREAT|0666);
ret = msgctl(id_coda,IPC_RMID,0);
id_coda = msgget(key, IPC_CREAT|IPC_EXCL|0666);
if( id_coda == -1 ){
printf("cannot install server queue, please check with the problem\n");
exit(-1);
}
}

//close(sd);
if(fork()==0){


while(1) {

if ( msgrcv(id_coda, &request_message, sizeof(request), 1, FLAG) == -1) {
printf("message receive error, please check with the problem\n");
}
else {


new_message = malloc(sizeof(request_msg));
if(!new_message){
printf("cannot allocate new request message buffer \n");
exit(-1);
}
memcpy((char*)new_message,(char*)&request_message,sizeof(request_msg));



if( pthread_create(&tid, NULL, visualizza, (void *)new_message) != 0){
printf("cannot create new thread \n");
exit(-1);
}



}
}/* end while */
}/* end fork*/

// prenota
if(fork()==0){while(1) {

if ( msgrcv(id_coda, &request_mes_pren, sizeof(request_pren), 2, FLAG) == -1) {
printf("message receive error, please check with the problem\n");
}
else {

new_mes_pren = malloc(sizeof(request_msg_pren));
if(!new_mes_pren){
printf("cannot allocate new request message buffer \n");
exit(-1);
}
memcpy((char*)new_mes_pren,(char*)&request_mes_pren,sizeof(request_pren));

if( pthread_create(&tid, NULL, prenota, (void *)new_mes_pren ) != 0){
printf("cannot create new thread \n");
exit(-1);
}



}
}/* end while */
}/* end fork*/


// cancella
if(fork()==0){ while(1) {

if ( msgrcv(id_coda, &request_mes_canc, sizeof(request_canc), 3, FLAG) == -1) {
printf("message receive error, please check with the problem\n");
}
else {

new_mes_canc = malloc(sizeof(request_msg_canc));
if(!new_mes_canc){
printf("cannot allocate new request message buffer \n");
exit(-1);
}
memcpy((char*)new_mes_canc,(char*)&request_mes_canc,sizeof(request_canc));

if( pthread_create(&tid, NULL, cancella, (void *)new_mes_canc ) != 0){
printf("cannot create new thread \n");
exit(-1);
}



}
}/* end while */
}/* end fork*/
wait(&status);
eli=msgctl(ds_shm,IPC_RMID,NULL);
if(eli == -1) printf("Errore nella chiamata msgctl");
elimina_sem(id_sem);
}

void visualizza(request_msg *request_message){

int status,i,j,occ;
char *p;

printf("asked service of type %d - response channel is %d\n", request_message->req.service_code,request_message->req.response_channel);

response_message.mtype = 1;

p = shmat(ds_shm, 0, SHM_R);
if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}

for(i=0;i<R;i++){
for(j=0;j<C;j++){
strncpy(prenotazioni[i][j].pren,p,6);
p+=6;
}
}

for(i=0;i<R;i++)
for(j=0;j<C;j++){
occ=strncmp(prenotazioni[i][j].pren,"0000",4);
if(occ==0) response_message.posti[i][j]=0;
else response_message.posti[i][j]=1;
}

if ( msgsnd(request_message->req.response_channel, &response_message, sizeof(response_msg), FLAG) == -1 ) {
printf("cannot return response to the client\n");
exit(-1);
}
i=shmdt(p);
free(request_message);
status = 0;
pthread_exit((void *)&status);

}

void prenota (request_msg_pren *request_mes_pren){

response_msg_canc risposta_pren;
int status,occ,i,j,dist,trovato,cod,sd,doppio,conta=0;
char *p,c[6],*scorri_mem;

risposta_pren.mtype = 2;

sem_wait(id_sem);

p = shmat(ds_shm, 0, SHM_R);

if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}
scorri_mem=p;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
strncpy(prenotazioni[i][j].pren,scorri_mem,6);
scorri_mem+=6;
}
}
scorri_mem=p;

for(i=0;i<R;i++)
for(j=0;j<C;j++){
occ=strncmp(prenotazioni[i][j].pren,"0000",4);
if(occ==0) response_message.posti[i][j]=0;
else response_message.posti[i][j]=1;
}


for(i=0;i<R;i++)
for(j=0;j<C;j++){
if(request_mes_pren->req.posti[i][j]==1)
if(request_mes_pren->req.posti[i][j]==response_message.posti[i][j])
trovato=1;
if(request_mes_pren->req.posti[i][j]==0) conta++;
}
i=shmdt(p);
p = shmat(ds_shm, 0, SHM_R);
scorri_mem=p;
if(trovato==1 || conta==(R*C)){ strcpy(risposta_pren.risp,"prenotazione non effettuata");}
else {
do{
cod=random();
ito(cod,c);
doppio=0;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
occ=strncmp(prenotazioni[i][j].pren,c,4);
if(occ==0) {doppio=1;break;}
}
}
}while(doppio==1);
strcpy(risposta_pren.risp,"prenotazione effettuata con codice: ");
strncat(risposta_pren.risp,c,6);

i=shmdt(p);
p = shmat(ds_shm, 0, SHM_W);
scorri_mem=p;
for(i=0;i<R;i++){
for(j=0;j<C;j++){
if(request_mes_pren->req.posti[i][j]==1){

strncpy(scorri_mem,c,6);
if(j<(C-1)) *(scorri_mem+4)=' ';
else (*(scorri_mem+4)='\n');
}
*(scorri_mem+5)='\0';
scorri_mem+=6;
}
}
}
close(STDOUT);
scorri_mem=p;
sd=open(CINEMA,O_RDWR|O_TRUNC);
dup(sd);
for(i=0;i<R;i++){
for(j=0;j<C;j++){
write (sd,scorri_mem,5);
scorri_mem+=6;
}
}
//fflush(STDOUT);

if ( msgsnd(request_mes_pren->req.response_channel, &risposta_pren, sizeof(response_msg_canc), FLAG) == -1 ) {
printf("cannot return response to the client\n");
exit(-1);
}
close(sd);
sem_signal(id_sem);
free(request_mes_pren);
status = 0;
pthread_exit((void *)&status);

}


void cancella (request_msg_canc *request_mes_canc){

response_msg_canc risposta;
int status,occ,i,j,dist,sd,trovato=0;
char *p,*scorri_mem;

risposta.mtype = 3;

p = shmat(ds_shm, 0, SHM_W);
if(p==(char*)-1){printf("Errore nella chiamata shmat\n"); exit(1);}
scorri_mem=p;
for(i=0;i<R;i++)
for(j=0;j<C;j++){
occ=strncmp(scorri_mem,request_mes_canc->req.codice,4);
if(occ==0) {
trovato++;
if(j<C-1){ strcpy(scorri_mem,"0000 \0");}
else { strcpy(scorri_mem,"0000\n");}
}
scorri_mem+=6;
}
i=shmdt(p);

sd=open(CINEMA,O_RDWR|O_TRUNC);
p = shmat(ds_shm, 0, SHM_R);
scorri_mem=p;

for(i=0;i<R;i++){
for(j=0;j<C;j++){
write(sd,scorri_mem,5);
scorri_mem+=6;
}
}

if(trovato>0) strcpy(risposta.risp,"cancellazione effettuata");
else { strcpy(risposta.risp,"codice inesistente");}

if ( msgsnd(request_mes_canc->req.response_channel, &risposta, sizeof(response_msg_canc), FLAG) == -1 ) {
printf("cannot return response to the client\n");
exit(-1);
}

close(sd);
i=shmdt(p);
free(request_mes_canc);
status = 0;
pthread_exit((void *)&status);

}


void ito(int casuale,char c[]){

div_t divisione;
int i,k,j,num=1;


if(casuale > 999999999) k=9;
else k=8;

for(j=0;j<k;j++)
num=num*10;

for(i=0;i<4;i++){
divisione= div(casuale,num);
switch(divisione.quot) {
case 0: c[i]='0'; break;
case 1: c[i]='1'; break;
case 2: c[i]='2'; break;
case 3: c[i]='3'; break;
case 4: c[i]='4'; break;
case 5: c[i]='5'; break;
case 6: c[i]='6'; break;
case 7: c[i]='7'; break;
case 8: c[i]='8'; break;
case 9: c[i]='9'; break;
}
casuale=divisione.rem;
num=num/10;;
}
c[4]=' ';
c[5]='\0';
return ;
}
int crea_init_sem(key_t chiave, int val)
{
int sem;
sem=semget(chiave,1,IPC_CREAT|0666);
if (sem==-1)
{
printf("Impossibile creare il semaforo\n");
exit(1);
}
semctl(sem,0,SETVAL,val);
return(sem);
}

void elimina_sem(int id_sem)
{
if(semctl(id_sem,IPC_RMID,0)==-1)
{
printf("Impossibile eliminare il semaforo\n");
exit(1);
}
}

int sem_wait(int sem)
{
struct sembuf operazione[1]={{0,-1,0}};
return semop(sem,operazione,1);
}

int sem_signal(int sem)
{
struct sembuf operazione[1]={{0,+1,0}};
return semop(sem,operazione,1);
}

这就是崩溃:

*** stack smashing detected ***: ./Client
======= Memory map: ========

uca@luca-8:~/Scrivania/tesina/ufficial$ ./Client

1 visualizza;

2 prenota;

3 cancella;

4 esci;

2

Digitare il numero di posti che si vuole prenotare compreso tra 1 e 15

2

Digitare il 1° posto nel formato 'fila poltrona' con fila compresa tra 1..3 e poltrona tra 1..5

3 1

Digitare il 2° posto nel formato 'fila poltrona' con fila compresa tra 1..3 e poltrona tra 1..5

3 2

00000

00000

11000

prenotazione effettuata con codice: 1804

*** stack smashing detected ***: ./Client terminated

======= Backtrace: =========

/lib/i386-linux-gnu/libc.so.6(__fortify_fail+0x45)[0x9408d5]

/lib/i386-linux-gnu/libc.so.6(+0xe7887)[0x940887]

./Client[0x8048c8d]

./Client[0x80487aa]

/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x872113]

./Client[0x80485c1]

======= Memory map: ========

0019d000-0019e000 r-xp 00000000 00:00 0 [vdso]

00525000-00541000 r-xp 00000000 08:01 2360250 /lib/i386-linux-gnu/libgcc_s.so.1

00541000-00542000 r--p 0001b000 08:01 2360250 /lib/i386-linux-gnu/libgcc_s.so.1

00542000-00543000 rw-p 0001c000 08:01 2360250 /lib/i386-linux-gnu/libgcc_s.so.1

00859000-009cf000 r-xp 00000000 08:01 2360229 /lib/i386-linux-gnu/libc-2.13.so

009cf000-009d1000 r--p 00176000 08:01 2360229 /lib/i386-linux-gnu/libc-2.13.so

009d1000-009d2000 rw-p 00178000 08:01 2360229 /lib/i386-linux-gnu/libc-2.13.so

009d2000-009d5000 rw-p 00000000 00:00 0

00b18000-00b36000 r-xp 00000000 08:01 2360216 /lib/i386-linux-gnu/ld-2.13.so

00b36000-00b37000 r--p 0001d000 08:01 2360216 /lib/i386-linux-gnu/ld-2.13.so

00b37000-00b38000 rw-p 0001e000 08:01 2360216 /lib/i386-linux-gnu/ld-2.13.so

08048000-0804a000 r-xp 00000000 08:01 5636693 /home/luca/Scrivania/tesina/ufficial/Client

0804a000-0804b000 r--p 00001000 08:01 5636693 /home/luca/Scrivania/tesina/ufficial/Client

0804b000-0804c000 rw-p 00002000 08:01 5636693 /home/luca/Scrivania/tesina/ufficial/Client

0809c000-080bd000 rw-p 00000000 00:00 0 [heap]

b78b1000-b78b2000 rw-p 00000000 00:00 0

b78bf000-b78c3000 rw-p 00000000 00:00 0

bf8d0000-bf8f1000 rw-p 00000000 00:00 0 [stack]

Annullato

luca@luca-8:~/Scrivania/tesina/ufficial$

最佳答案

这很可能是由这一行引起的:scanf("%s",preno);。用户可以输入超过 4 个非空格字符并溢出 preno[5] 缓冲区。考虑对要读取的字符数添加限制(例如 "%4s")。

我还看到很多 strcpy - 如果缓冲区的容量小于源字符串,则有可能导致缓冲区溢出和粉碎堆栈。即使您正确分配了空间,也请考虑将它们全部更改为 strncpy

关于c - 在 C 中预订客户端-服务器时检测到堆栈崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11309979/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com