PDA

View Full Version : [C] Segmentation fault


Manugal
02-01-2007, 17:53
Ciao.

Potreste aiutarmi a scovare l'errore in queste due (o in una di queste due funzioni) ? La funzione intepret_file legge da un file una linea di testo che corrisponde ad un comando Unix e sostituisce gli argomenti $i con gli argomenti passati a linea di comando. La funzione parse invece esegue tutte le operazioni di shell expansion. Ho provato con un file di prova contenente tre linee:

ls $1 $4
ps $3
uname $2

dove $1="-l" $2="*.c" $3="aux" $4="-r".

Il problema avviene quando va a leggere la terza linea e chiama la funzione parse. Verso la fine nel while(cnt<pwordexp.we_wordc) va in segmentation fault sull'istruzione "args[i]=(char *)calloc(strlen(pwordexp.we_wordv[i-2])+1,sizeof(char));" (nonostante args[i]=NULL). Non riesco a capire perché. Questo è il codice delle due funzioni:

interpret_file.c

#include "functions.h"

void interpret_file(int numargs,char **args){
int fdin,i,j,status,offset;
pid_t pid;
ssize_t nread;
char *buf=(char *)malloc(sizeof(char)*MAX_CMD_LEN);
if((fdin=open(args[1],O_RDONLY)) == -1){
if(errno==EINTR){
if(buf!=NULL){
free(buf);
buf=NULL;
}
close(fdin);
exit(OK);
}
else{
perror("open error");
if(buf!=NULL){
free(buf);
buf=NULL;
}
close(fdin);
exit(OPEN_ERR);
}
}
while((nread=read(fdin,buf,MAX_CMD_LEN)) > 0 || nread == -1){
char **passargs=(char **)calloc(MAX_ARGS,sizeof(char *));
if(nread == -1){
if(errno==EINTR){
if(buf!=NULL){
free(buf);
buf=NULL;
}
close(fdin);
exit(OK);
}
else{
perror("read error");
if(buf!=NULL){
free(buf);
buf=NULL;
}
close(fdin);
exit(OPEN_ERR);
}
}
j=0;
offset=0;
char *pbuf=buf;
if(nread < MAX_CMD_LEN){
if(errno==EINTR){
if(buf!=NULL){
free(buf);
buf=NULL;
}
close(fdin);
exit(OK);
}
else{
perror("read error");
if(buf!=NULL){
free(buf);
buf=NULL;
}
close(fdin);
exit(READ_ERR);
}
}
while(*pbuf != '$'){
++pbuf;
++offset;
}
passargs[j]=(char *)calloc(offset,sizeof(char));
strncpy(passargs[j],buf,offset-1);
passargs[offset]='\0';
++j;
for( ; *pbuf=='$'; pbuf+=2){
++pbuf;
switch(*pbuf){
case '1':
i=2;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '2':
i=3;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '3':
i=4;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '4':
i=5;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '5':
i=6;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '6':
i=7;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '7':
i=8;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '8':
i=9;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
case '9':
i=10;
passargs[j]=(char *)calloc(strlen(args[i]),sizeof(char));
strcpy(passargs[j],args[i]);
++j;
break;
default:
printf("Too many arguments\n");
if(buf!=NULL){
free(buf);
buf=NULL;
}
if(passargs!=NULL){
free(passargs);
passargs=NULL;
}
exit(ERR_GEN);
}
}
parse(NULL,passargs);
if((pid=fork()) < 0){
perror("fork error");
if(passargs!=NULL){
free(passargs);
passargs=NULL;
}
if(buf!=NULL){
free(buf);
buf=NULL;
}
exit(FORK_ERR);
}
if(pid == 0){
execvp(passargs[0],passargs);
perror("exec failed");
if(passargs!=NULL){
free(passargs);
passargs=NULL;
}
if(buf!=NULL){
free(buf);
buf=NULL;
}
exit(EXEC_ERR);
}
if(pid > 0){
if (waitpid(pid,&status,0) == -1){
if(errno!=EINTR){
perror("waitpid error");
if(passargs!=NULL){
free(passargs);
passargs=NULL;
}
if(buf!=NULL){
free(buf);
buf=NULL;
}
exit(WAIT_ERR);
}
else{
kill(pid,SIGTERM);
do{
if (waitpid(pid,&status,0) != -1)
break;
}while(errno==EINTR);
}
}
}
if(passargs!=NULL){
free(passargs);
passargs=NULL;
}
}
close(fdin);
if(buf!=NULL){
free(buf);
buf=NULL;
}
}


parse.c

#include "functions.h"

void parse(char *name, char **args){
int i=0,j=0,cnt=0;
char *s;
if(args[i] == NULL)
args[i]=(char *)malloc(sizeof(char)*COMM_LENGTH+1);
if (strtok(name," ") != NULL){
strcpy(args[i],name);
++i;
}
while((s=strtok(NULL," ")) != NULL){
args[i]=(char *)malloc(sizeof(char)*strlen(s)+1);
sprintf(args[i],"%s",s);
++i;
}
if(args[i] == NULL)
args[i]=NULL;
if(s!=NULL){
free(s);
s=NULL;
}
int ret;
i=1;
while(args[i] != NULL){
if(*args[i] == '-'){
++i;
++j;
continue;
}
if ((ret=wordexp(args[i],&pwordexp,0)) == 0)
++i;
else{
printf("wordexp error");
if(args!=NULL){
free(args);
args=NULL;
}
exit(WRDEXP_ERR);
}
}
if(j>0){
i=j+1;
while(cnt<pwordexp.we_wordc){
if(args[i]==NULL)
args[i]=(char *)calloc(strlen(pwordexp.we_wordv[i-2])+1,sizeof(char));
strcpy(args[i],pwordexp.we_wordv[i-2]);
++cnt;
++i;
}
}
args[i]=NULL;
wordfree(&pwordexp);
}


Grazie.

Manugal
02-01-2007, 21:31
Ho risolto. Praticamente era la variabile wordexp che non veniva inizializzata per quel comando nella funzione parse e naturalmente non riusciva ad allocare memoria. Grazie lo stesso. :)

trallallero
03-01-2007, 08:15
quando succedono queste cose perché non fai una bella strace (da quel che vedo al volo sei su linux, o sbaglio ? )

strace -f -F -s 1024 -o file.trace ./<nome prog>

Manugal
03-01-2007, 10:17
Eh infatti cercavo un utility che mi facilitasse il compito. Grazie, ne terrò conto per il prossimo. ;)

trallallero
03-01-2007, 10:42
Eh infatti cercavo un utility che mi facilitasse il compito. Grazie, ne terrò conto per il prossimo. ;)
di niente :)

l'alternativa é printf fino alla nausea :D